﻿Imports System.ComponentModel

''' <summary>
''' This class will expose the Graph library through the Interface
''' </summary>
''' <remarks></remarks>
Public Class clsGraph
    Implements WRDB.Interfaces.clsGraph

    Public Sub New()
        GroupFileName = ""
    End Sub

    Public ReadOnly Property RegAppGraph() As String
        Get
            Return REGAPP
        End Get
    End Property

    Public Sub ShowGraph(Optional OwnerForm As Form = Nothing, Optional GraphFile As String = "", Optional LoadLast As Boolean = False, Optional FormCaption As String = "WRDB Graph") Implements WRDB.Interfaces.clsGraph.ShowGraph
        Updates = New clsUpdates("WRDB", "www.wrdb.com")
        With New frmGraph
            .GISForm = OwnerForm
            .mnuHelpUpdates.Visible = False 'todo: enhance options form to allow for checking of updates (need update location, auto-check, etc.)
            .LoadLast = LoadLast
            .LoadFile = GraphFile
            'GroupFileName = GraphFile
            .FormCaption = FormCaption
            If OwnerForm Is Nothing Then 'is stand-alone application
                .ShowDialog()
            Else
                .Show(OwnerForm) 'is called from wrdb
            End If
        End With
    End Sub

    ''' <summary>
    ''' Create graph of specified type using data queries from current working table
    ''' </summary>
    ''' <param name="ProjectName">WRDB Project Name</param>
    ''' <param name="TableName">Working table name</param>
    ''' <param name="GraphType">Type of graph to create</param>
    ''' <param name="BypassManageSeries">If true, will NOT show manage data series on startup</param>
    ''' <param name="SqlString">Last SQL string used to select data</param>
    ''' <remarks></remarks>
    Public Sub ShowGraph(OwnerForm As Form, ProjectName As String, TableName As String, GraphType As WRDB.Interfaces.clsGraph.enumGraphType, ByVal BypassManageSeries As Boolean, ByVal SqlString As String) Implements WRDB.Interfaces.clsGraph.ShowGraph
        Updates = New clsUpdates("WRDB", "www.wrdb.com")
        GraphForm = Nothing
        GraphForm = New frmGraph
        With GraphForm
            .GISForm = OwnerForm
            .mnuHelpUpdates.Visible = False 'is called from wrdb
            .Show()
            OpenTables.Clear()
            Dim tbl As New clsTable(GroupFileName, ExpertMode)
            tbl.CreateWRDBTable(ProjectName, clsTable.enumTableType.WRDB6)
            tbl.TableName = TableName
            tbl.SqlString = SqlString
            tbl.CreateTempData()
            OpenTables.Add(tbl)
            ActiveGraphTab(0).GraphType = GraphType
            GraphForm.ChangeGraphType(GraphType)
            'ActiveGraphTab(0).Reset()
            If Not BypassManageSeries Then GraphForm.ManageSeries(False)
        End With
    End Sub

    ''' <summary>
    ''' Create graph of specified type using data queries from current working table
    ''' </summary>
    ''' <param name="BMDFile">Name of data file to load</param>
    ''' <param name="GraphType">Type of graph to create</param>
    ''' <param name="BypassManageSeries">If true, will NOT show manage data series on startup</param>
    ''' <remarks></remarks>
    Public Sub ShowGraph(OwnerForm As Form, BMDFile As String, GraphType As WRDB.Interfaces.clsGraph.enumGraphType, BypassManageSeries As Boolean, Optional FormCaption As String = "WRDB Graph") Implements WRDB.Interfaces.clsGraph.ShowGraph
        Updates = New clsUpdates("WRDB", "www.wrdb.com")
        GraphForm = Nothing
        GraphForm = New frmGraph
        With GraphForm
            .mnuHelpUpdates.Visible = False 'is called from wrdb
            .FormCaption = FormCaption
            .Show()
            OpenTables.Clear()
            Dim tbl As New clsTable(GroupFileName, ExpertMode)
            If IO.Path.GetExtension(BMDFile).ToUpper = ".BMD2" Then
                tbl.CreateBMD2Table(BMDFile)
            Else
                tbl.CreateBMDTable(BMDFile)
            End If
            OpenTables.Add(tbl)
            ActiveGraphTab(0).GraphType = GraphType
            GraphForm.ChangeGraphType(GraphType)
            If Not BypassManageSeries Then GraphForm.ManageSeries(False)
        End With
    End Sub

    ''' <summary>
    ''' Add all data from first open table and create series and also add calculated series with probability fit
    ''' </summary>
    ''' <param name="GraphNotes">Additional notes that can be displayed on graph</param>
    ''' <remarks></remarks>
    Public Sub AddSeries(ByVal StationID As String, ByVal PCode As String, ByVal ProbOption As enumProbOption, ByVal ProbFit As enumProbFit, ByVal GraphNotes As String)
        Try
            With ActiveGraphTab(0)
                .GraphOptions.NoteText = GraphNotes
                If .AddSeries(OpenTables(0), StationID, PCode, Date.MinValue, enumTimeWindow.All, StationID, PCode, "", clsSeries.enumYAxis.Left, clsSeries.enumYAxisIndex.Axis_1, False) Then
                    If .GraphType = enumGraphType.Probability Then
                        Dim ser As clsSeriesProbability = .Series(.Series.Count - 1)
                        ser.ProbOption = ProbOption
                        Dim label As String = String.Format("{0} - {1} Fit", ser.Label, Choose(ProbFit + 1, "Normal", "Log-Normal", "Log-Pearson III"))
                        Dim zc As New ZedGraph.LineItem(label, New ZedGraph.PointPairList, ser.LineColor, SymbolType.None, 1)
                        Dim FitStats As String = ""
                        frmSeries.ComputeProbFit(enumProbFit.LogPearson3, CType(ser, clsSeriesProbability).ProbOption, ser.ZedCurve, zc, FitStats)
                        .AddSeries(ser, zc, FitStats)
                        .GraphOptions.NotePosition = IIf(ProbOption = enumProbOption.GreaterThan_Decr Or ProbOption = enumProbOption.LessThan_Incr, enumNotePosition.TopLeft, enumNotePosition.TopRight)
                        .Zed.GraphPane.YAxis.Type = IIf(ProbFit = enumProbFit.Normal, AxisType.Linear, AxisType.Log)
                        If .Zed.GraphPane.YAxis.Type = AxisType.Log Then 'auto max value isn't dependable (too large); do it manually
                            Dim max As Double = Double.MinValue
                            With .Zed.GraphPane.CurveList(.Zed.GraphPane.CurveList.Count - 1)
                                For i As Integer = 0 To .NPts - 1
                                    max = Math.Max(max, .Points(i).Y)
                                Next
                            End With
                            .Zed.GraphPane.YAxis.Scale.MaxAuto = False
                            .Zed.GraphPane.YAxis.Scale.Max = 10 ^ (Math.Truncate(Math.Log10(max - 0.00001)) + 1)
                        End If
                    End If
                End If
                .Zed.AxisChange()
                .Zed.Refresh()
            End With
            GraphForm.EnableMenus()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Add all data from first open table and create series
    ''' </summary>
    Public Sub AddSeries(StationID As String, PCode As String, Optional DepthPCode As String = "Depth") Implements WRDB.Interfaces.clsGraph.AddSeries
        With ActiveGraphTab(0)
            .AnimationInfo.DepthVariable = DepthPCode
            Dim DateList As String = ""
            Dim tw As enumTimeWindow = enumTimeWindow._1_Hour
            Select Case .GraphType
                Case enumGraphType.Depth, enumGraphType.Profile, enumGraphType.Scatter, enumGraphType.Width
                    With OpenTables(0)
                        DateList = ListToString(.GetDateList(StationID, PCode))
                        Select Case .TableType
                            Case clsTable.enumTableType.BMD, clsTable.enumTableType.BMD2 : tw = enumTimeWindow.BMD
                        End Select
                    End With
            End Select
            .AnimationInfo.TimeWindow = tw
            .AddSeries(OpenTables(0), StationID, PCode, Date.MinValue, tw, StationID, PCode, DateList, clsSeries.enumYAxis.Left, clsSeries.enumYAxisIndex.Axis_1, False)
            .Zed.AxisChange()
            .Zed.Refresh()
            GraphForm.ResetAnimationLimits()
            GraphForm.EnableMenus()
        End With
    End Sub

    ''' <summary>
    ''' Add all data from first open table and create longitudinal profile series using distances and stations from GIS map
    ''' </summary>
    Public Sub AddSeries(BranchID As String, dictProfile As Generic.Dictionary(Of Double, String), PCode As String, DateTime As Date) Implements WRDB.Interfaces.clsGraph.AddSeries
        Dim DateList As String = ""
        Dim tw As enumTimeWindow = enumTimeWindow._1_Hour
        With ActiveGraphTab(0)
            Select Case .GraphType
                Case enumGraphType.Profile, enumGraphType.Width
                    .ProfileXPlot = clsGraphTab.enumProfileXPlot.RiverMile
                    With OpenTables(0)
                        DateList = ListToString(.GetDateList("", PCode))
                        If Not .BranchName.Contains(BranchID) Then .BranchName.Add(BranchID)
                        For Each kv As KeyValuePair(Of Double, String) In dictProfile
                            Dim supt As clsTable.structStationSupport = Nothing
                            If .StationSupport.ContainsKey(kv.Value) Then
                                supt = .StationSupport(kv.Value)
                            Else
                                .StationSupport.Add(kv.Value, supt)
                            End If
                            supt.StationID = kv.Value
                            supt.RiverMile = kv.Key
                            supt.Name = ""
                            supt.BranchID = BranchID
                            .StationSupport(kv.Value) = supt
                        Next
                        Select Case .TableType
                            Case clsTable.enumTableType.BMD, clsTable.enumTableType.BMD2 : tw = enumTimeWindow.BMD
                        End Select
                    End With
            End Select
            .AnimationInfo.TimeWindow = tw
            .AddSeries(OpenTables(0), BranchID, PCode, DateTime, tw, BranchID, PCode, DateList, clsSeries.enumYAxis.Left, clsSeries.enumYAxisIndex.Axis_1, False)
            ActiveGraphTab.ResetProfileScales()
            .Zed.AxisChange()
            .Zed.Refresh()
            GraphForm.ResetAnimationLimits()
            GraphForm.EnableMenus()
        End With
    End Sub

    ''' <summary>
    ''' Add all data from first open table and create series
    ''' </summary>
    Public Sub AddSeries(ByVal StationID As String, ByVal PCode As String, ByVal ShowLine As Boolean, ByVal ShowSymbol As Boolean, Optional ByVal GraphNotes As String = "")
        Try
            With ActiveGraphTab(0)
                .AddSeries(OpenTables(0), StationID, PCode, Date.MinValue, enumTimeWindow.All, StationID, PCode, "", clsSeries.enumYAxis.Left, clsSeries.enumYAxisIndex.Axis_1, False)
                With .Series(.Series.Count - 1)
                    .LineType = IIf(ShowLine, clsSeries.enumLineType.Solid, clsSeries.enumLineType.None)
                    .SymbolType = IIf(ShowSymbol, clsSeries.enumSymbolType.Circle, clsSeries.enumSymbolType.None)
                    If ActiveGraphTab(0).GraphType = enumGraphType.Profile Then .SymbolType = clsSeries.enumSymbolType.Box_Whisker
                End With
                If GraphNotes <> "" Then
                    .GraphOptions.NoteText = GraphNotes
                    .GraphOptions.NotePosition = enumNotePosition.TopLeft
                End If
                .Zed.AxisChange()
                .Zed.Refresh()
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Add new graph tab and make active
    ''' </summary>
    Public Sub AddGraphTab()
        GraphForm.AddGraphTab()
    End Sub

    Public Sub iShowGraph(Optional ByVal OwnerForm As Form = Nothing, Optional ByVal GraphFile As String = "", Optional ByVal LoadLast As Boolean = False)
        ShowGraph(OwnerForm, GraphFile, LoadLast)
    End Sub

End Class

Friend Class clsAnimationInfo

    Public Sub New()
        Speed = 3
        ToolbarVisible = False
        NumIntervals = 8
        TimeWindow = enumTimeWindow.None
    End Sub

    ''' <summary>
    ''' For profiles
    ''' </summary>
    Friend Property DateTime() As Date

    ''' <summary>
    ''' For profiles
    ''' </summary>
    Friend Property MaxDate() As Date

    ''' <summary>
    ''' For profiles
    ''' </summary>
    Friend Property MinDate() As Date

    ''' <summary>
    ''' For time series
    ''' </summary>
    Friend Property NodeNum() As Integer

    ''' <summary>
    ''' Min is zero, step is always 1
    ''' </summary>
    Friend Property MaxNode() As Integer

    ''' <summary>
    ''' Number of intervals for histogram
    ''' </summary>
    Friend Property NumIntervals() As Integer

    Private _Speed As Integer

    ''' <summary>
    ''' Relative speed from 1 to 5 (1 is slowest)
    ''' </summary>
    Friend Property Speed() As Integer
        Get
            Return _Speed
        End Get
        Set(ByVal value As Integer)
            _Speed = Math.Min(7, Math.Max(1, value))
        End Set
    End Property

    Private _TimeStep As Integer

    ''' <summary>
    ''' Animation timestep in minutes (take from TimeWindow)
    ''' </summary>
    Friend Property TimeStep() As Integer
        Get
            If _TimeStep = 0 Then
                Return 1 '60
            Else
                Return _TimeStep
            End If
        End Get
        Set(ByVal value As Integer)
            _TimeStep = value
        End Set
    End Property

    Friend Property TimeWindow() As enumTimeWindow

    ''' <summary>
    ''' Is toolbar visible?
    ''' </summary>
    Friend Property ToolbarVisible() As Boolean

    ''' <summary>
    ''' The name of the variable associated with depth 
    ''' Used for plotting depth profiles from BMD files
    ''' </summary>
    Friend Property DepthVariable As String

End Class

''' <summary>
''' This class was created to store and display axis options in the properties grid
''' </summary>
<DefaultProperty("Title")> _
Friend Class clsAxis

    Friend Enum enumAxis
        XAxis
        X2Axis
        YAxis
        Y2Axis
    End Enum
    Private _Axis As ZedGraph.Axis
    Private _AxisNum As Integer
    Private _AxisType As enumAxis
    Private Zed As ZedGraph.ZedGraphControl
    Private _FontScaleFactor As Double

    Friend Structure structAxisExtra
        Dim AutoTitle As Boolean
        Dim MinLimit As String
        Dim MaxLimit As String
        Dim AutoMaxLog As Boolean
        Dim AutoMinLog As Boolean
        Dim TitleFont As Font
        Dim LabelFont As Font
        Dim ScaleType As enumScaleType
        Sub Initialize()
            AutoTitle = True
            MinLimit = "Not Set"
            MaxLimit = "Not Set"
            AutoMinLog = True
            AutoMaxLog = True
            TitleFont = New Font("Tahoma", 8)
            LabelFont = New Font("Tahoma", 8)
            ScaleType = enumScaleType.Linear
        End Sub
    End Structure

    ''' <summary>
    ''' These are identical to ZedGraph.AxisType values, but have been renamed for property grid
    ''' </summary>
    ''' <remarks>Only linear, log, date, probability, datedual, and datejulian are being used</remarks>
    Friend Enum enumScaleType
        Linear
        Log
        [Date]
        Text
        Ordinal
        DateAsOrdinal
        LinearAsOrdinal
        Exponent
        Probability
        Date_Adaptive 'same as DateDual
        Date_Julian 'will remap this to date or date_dual but will reset all to same year
    End Enum

    ''' <summary>
    ''' Sets default values for new instance
    ''' </summary>
    ''' <param name="Zed">ZedGraph control that is already on form</param>
    Friend Sub New(ByRef Zed As ZedGraph.ZedGraphControl, ByVal AxisType As enumAxis, ByVal AxisNum As Integer, FontScaleFactor As Double)
        Me.Zed = Zed
        _AxisType = AxisType
        _AxisNum = AxisNum
        _FontScaleFactor = FontScaleFactor
        Select Case AxisType
            Case enumAxis.XAxis : _Axis = Zed.GraphPane.XAxis
            Case enumAxis.X2Axis : _Axis = Zed.GraphPane.X2Axis
            Case enumAxis.YAxis
                If AxisNum > Zed.GraphPane.YAxisList.Count - 1 Then Zed.GraphPane.YAxisList.Add("")
                _Axis = Zed.GraphPane.YAxisList(AxisNum)
            Case enumAxis.Y2Axis
                If AxisNum > Zed.GraphPane.Y2AxisList.Count - 1 Then Zed.GraphPane.Y2AxisList.Add("")
                _Axis = Zed.GraphPane.Y2AxisList(AxisNum)
        End Select
        _Axis.Scale.MagAuto = False
        If _Axis.Tag Is Nothing Then
            'following added 12/17/15 because axes not getting initialized correctly for FFS graph file containing no graphs (tables only)
            Dim _AxisExtra As structAxisExtra = Nothing
            _AxisExtra.Initialize()
            _Axis.Tag = _AxisExtra
        End If

    End Sub

    ''' <summary>
    ''' Return underlying Zedgraph axis so can get at all properties
    ''' </summary>
    Friend ReadOnly Property ZedAxis() As ZedGraph.Axis
        Get
            Return _Axis
        End Get
    End Property

    Friend Shared Function AxisExtra(ByVal AxisTag As Object) As structAxisExtra
        Dim _AxisExtra As structAxisExtra = Nothing
        If AxisTag IsNot Nothing AndAlso TypeOf AxisTag Is structAxisExtra Then
            _AxisExtra = AxisTag
        Else
            _AxisExtra.Initialize()
        End If
        Return _AxisExtra
    End Function



#Region "General Properties"

    <DisplayName("1. Auto Axis Title"), Category("General"), Description("If true will automatically set the axis title depending on what data are displayed")> _
    Public Property AutoTitle() As Boolean
        Get
            Return AxisExtra(_Axis.Tag).AutoTitle
        End Get
        Set(ByVal value As Boolean)
            Dim _AxisExtra As structAxisExtra = AxisExtra(_Axis.Tag)
            _AxisExtra.AutoTitle = value
            _Axis.Tag = _AxisExtra
            If value And _Axis.IsVisible Then ActiveGraphTab.ResetYAxes()
        End Set
    End Property

    ''' <summary>
    ''' Title of x axis (Axis.Title.Text)
    ''' </summary>
    <DisplayName("2. Axis Title"), Category("General"), Description("Sets the title for the axis")> _
    Public Property Title() As String
        Get
            Return _Axis.Title.Text
        End Get
        Set(ByVal value As String)
            _Axis.Title.Text = value
            Dim _AxisExtra As structAxisExtra = AxisExtra(_Axis.Tag)
            _AxisExtra.AutoTitle = False
            _Axis.Tag = _AxisExtra
        End Set
    End Property

    ''' <summary>
    ''' Font for title of axis (Axis.Title.FontSpec)
    ''' </summary>
    <DisplayName("3. Title Font"), Category("General"), Description("Sets the axis title font")> _
    Public Property TitleFont() As Font
        Get
            Return AxisExtra(_Axis.Tag).TitleFont
        End Get
        Set(ByVal value As Font)
            Dim _AxisExtra As structAxisExtra = AxisExtra(_Axis.Tag)
            'round font sizes to integer since dialog only lets you select integers
            _AxisExtra.TitleFont = New Font(value.FontFamily, Math.Round(value.Size, 0), value.Style, GraphicsUnit.Point)
            _Axis.Title.FontSpec = GetFont(_AxisExtra.TitleFont, _Axis.Title.FontSpec, _FontScaleFactor)
            _Axis.Tag = _AxisExtra
        End Set
    End Property

    ''' <summary>
    ''' Font for labels on axis (Axis.Scale.FontSpec)
    ''' </summary>
    <DisplayName("4. Label Font"), Category("General"), Description("Sets the axis label font")> _
    Public Property LabelFont() As Font
        Get
            Return AxisExtra(_Axis.Tag).LabelFont
        End Get
        Set(ByVal value As Font)
            Dim _AxisExtra As structAxisExtra = AxisExtra(_Axis.Tag)
            'round font sizes to integer since dialog only lets you select integers
            _AxisExtra.LabelFont = New Font(value.FontFamily, Math.Round(value.Size, 0), value.Style, GraphicsUnit.Point)
            _Axis.Scale.FontSpec = GetFont(_AxisExtra.LabelFont, _Axis.Scale.FontSpec, _FontScaleFactor)
            _Axis.Tag = _AxisExtra
        End Set
    End Property

    ''' <summary>
    ''' Axis type (Axis.Type)
    ''' </summary>
    <DisplayName("5. Axis Type"), Category("General"), Description("Sets the scale type of the axis (e.g., date, logarithmic, etc.)"), TypeConverter(GetType(ConvAxisType))> _
    Public Property AxisType() As clsAxis.enumScaleType
        Get
            Return AxisExtra(_Axis.Tag).ScaleType
        End Get
        Set(ByVal value As clsAxis.enumScaleType)
            With _Axis
                Dim _AxisExtra As structAxisExtra = AxisExtra(.Tag)
                If .Scale.IsLog Then
                    .Scale.MinAuto = _AxisExtra.AutoMinLog
                    .Scale.MaxAuto = _AxisExtra.AutoMaxLog
                End If
                Dim PrevType As clsAxis.enumScaleType = _AxisExtra.ScaleType
                Select Case value
                    Case ZedGraph.AxisType.Date, ZedGraph.AxisType.DateAsOrdinal, enumScaleType.Date_Adaptive
                        .Scale.Format = MyDateFormat()
                        .Type = value
                    Case enumScaleType.Date_Julian
                        .Type = ZedGraph.AxisType.Date
                        .Scale.Format = MyMonthDayFormat()
                    Case Else
                        .Scale.Format = ""
                        .Scale.FormatAuto = True
                        .Type = value
                End Select
                _AxisExtra.ScaleType = value
                _Axis.Tag = _AxisExtra
                Select Case value
                    Case enumScaleType.Date, enumScaleType.DateAsOrdinal, enumScaleType.Date_Adaptive
                        If PrevType = enumScaleType.Date_Julian Then ActiveGraphTab.Refresh()
                    Case enumScaleType.Date_Julian
                        If PrevType <> value Then ActiveGraphTab.Refresh()
                End Select
                'ActiveGraphTab.Refresh() 'need to reacquire so series formed from julian days
            End With
            FixLogScale()
        End Set
    End Property

    ''' <summary>
    ''' Are gridlines visible? If yes, will be gray and dashed
    ''' </summary>
    <DisplayName("6. Auto-Magnitude?"), Category("General"), Description("If true, will automatically determine magnitude multiplier for large and small numbers (e.g., 10^3). Otherwise will use magnitude of 1.0")> _
    Public Property MagAuto() As Boolean
        Get
            Return _Axis.Scale.MagAuto
        End Get
        Set(ByVal value As Boolean)
            '_Axis.Scale.Mag = 1
            _Axis.Scale.MagAuto = value
        End Set
    End Property

    ''' <summary>
    ''' Are gridlines visible? If yes, will be gray and dashed
    ''' </summary>
    <DisplayName("7. Axis Is Visible?"), Category("General"), Description("Sets the visibility of the selected axis")> _
    Public Property Visible() As Boolean
        Get
            Return _Axis.IsVisible
        End Get
        Set(ByVal value As Boolean)
            _Axis.IsVisible = value
        End Set
    End Property

    ''' <summary>
    ''' Are gridlines visible? If yes, will be gray and dashed
    ''' </summary>
    <DisplayName("8. Show Gridlines?"), Category("General"), Description("Are major (and optionally minor) grid lines visible?")> _
    Public Property GridLines() As Boolean
        Get
            Return _Axis.MajorGrid.IsVisible
        End Get
        Set(ByVal value As Boolean)
            With _Axis.MajorGrid
                .IsVisible = value
                .Color = Color.DarkGray
                .DashOn = 5
                .DashOff = 2
                .PenWidth = 1
            End With
            _Axis.MinorGrid.IsVisible = value
        End Set
    End Property

    ''' <summary>
    ''' Are minor gridlines visible? If yes, will be gray and dashed
    ''' </summary>
    <DisplayName("9. Show Minor Gridlines?"), Category("General"), Description("Are minor grid lines visible? Show Gridlines must also be True for minor gridlines to appear.")> _
    Public Property GridLinesMinor() As Boolean
        Get
            Return _Axis.MinorGrid.IsVisible
        End Get
        Set(ByVal value As Boolean)
            With _Axis.MinorGrid
                .IsVisible = value And _Axis.MajorGrid.IsVisible
                .Color = Color.LightGray
                .DashOn = 3
                .DashOff = 3
                .PenWidth = 1
            End With
        End Set
    End Property
#End Region

#Region "Scale Properties"
    ''' <summary>
    ''' Is the minimum value automatically determined?
    ''' </summary>
    <DisplayName("1. Auto Scale Min?"), Category("Scale"), Description("Is the minimum value automatically determined?")> _
    Public Property AutoScaleMin() As Boolean
        Get
            With _Axis.Scale
                If ActiveGraphTab() Is Nothing Then Return 0
                If ActiveGraphTab.GraphType = enumGraphType.FlowDuration And _AxisType = enumAxis.XAxis Then
                    Return .Max = 0
                Else
                    Return .MinAuto
                End If
            End With
        End Get
        Set(ByVal value As Boolean)
            With _Axis.Scale
                If ActiveGraphTab() Is Nothing Then Exit Property
                If ActiveGraphTab.GraphType = enumGraphType.FlowDuration And _AxisType = enumAxis.XAxis Then
                    If value Then .Min = 0
                Else
                    .MinAuto = value
                End If
                If .IsLog Then
                    Dim _AxisExtra As structAxisExtra = AxisExtra(_Axis.Tag)
                    _AxisExtra.AutoMinLog = value
                    _Axis.Tag = _AxisExtra
                End If
            End With
            FixLogScale()
            ResetLimitMinMax()
        End Set
    End Property

    ''' <summary>
    ''' Set the minimum value for the axis
    ''' </summary>
    <DisplayName("2. Minimum Value"), Category("Scale"), Description("Set the minimum value for the axis if Auto Scale is false")> _
    Public Property Min() As String
        Get
            If _Axis.Type = ZedGraph.AxisType.Date Or _Axis.Type = ZedGraph.AxisType.DateDual Then
                Return Date.FromOADate(_Axis.Scale.Min).ToString(MyDateTimeFormat)
            ElseIf _Axis.Type = ZedGraph.AxisType.DateAsOrdinal Then
                Return Date.FromOADate(_Axis.Scale.Min).DayOfYear
            Else
                Return Math.Round(_Axis.Scale.Min, 3)
            End If
        End Get
        Set(ByVal value As String)
            With _Axis
                SetAxisLimit(value, .Type, .Scale.MinAuto, .Scale.Min)
            End With
            ResetLimitMinMax()
        End Set
    End Property

    ''' <summary>
    ''' Set the minimum limit value for the axis
    ''' </summary>
    <DisplayName("3. Minimum Limit"), Category("Scale"), Description("Set the minimum limit value for the axis; used by Zoom Limits (read-only; automatically set each time you manually set the axis min/max)"), [ReadOnly](True)> _
    Public Property MinLimit() As String
        Get
            With AxisExtra(_Axis.Tag)
                If _Axis.Type = ZedGraph.AxisType.Date Or _Axis.Type = ZedGraph.AxisType.DateDual Then
                    If IsDate(.MinLimit) Then
                        Return CDate(.MinLimit).ToString(MyDateTimeFormat)
                    Else
                        Return "Not Set"
                    End If
                ElseIf _Axis.Type = ZedGraph.AxisType.DateAsOrdinal Then
                    If IsNumeric(.MinLimit) AndAlso Math.Abs(Val(.MinLimit)) < 1.0E+300 Then
                        Return Date.FromOADate(_Axis.Scale.Min).DayOfYear
                    Else
                        Return "Not Set"
                    End If
                Else
                    If IsNumeric(.MinLimit) AndAlso Math.Abs(Val(.MinLimit)) < 1.0E+300 Then
                        Return Math.Round(Val(.MinLimit), 3)
                    Else
                        Return "Not Set"
                    End If
                End If
            End With
        End Get
        Set(ByVal value As String)
            Dim _AxisExtra As structAxisExtra = AxisExtra(_Axis.Tag)
            _AxisExtra.MinLimit = value
            _Axis.Tag = _AxisExtra
            If _Axis.IsVisible Then ActiveGraphTab.ResetYAxes()
        End Set
    End Property

    ''' <summary>
    ''' Is the maximum value automatically determined?
    ''' </summary>
    <DisplayName("4. Auto Scale Max?"), Category("Scale"), Description("Is the maximum value automatically determined?")> _
    Public Property AutoScaleMax() As Boolean
        Get
            With _Axis.Scale
                If ActiveGraphTab() Is Nothing Then Return 0
                If ActiveGraphTab.GraphType = enumGraphType.FlowDuration And _AxisType = enumAxis.XAxis Then
                    Return .Max = 100
                Else
                    Return .MaxAuto
                End If
            End With
        End Get
        Set(ByVal value As Boolean)
            With _Axis.Scale
                If ActiveGraphTab.GraphType = enumGraphType.FlowDuration And _AxisType = enumAxis.XAxis Then
                    If value Then .Max = 100
                Else
                    .MaxAuto = value
                End If
                FixLogScale()
            End With
            ResetLimitMinMax()
        End Set
    End Property

    Friend Sub FixLogScale()
        Try
            'this almost works, but causes a lot of other complications; because I have Zoom Limits, not so bad for user to have to manually set limits and live with defaults
            Exit Sub
            With _Axis.Scale
                If .IsLog Then 'by default, will give 7 log cycles--reduce to minimum required
                    'loop through all visible series and get min/max
                    Dim min As Double = Double.MaxValue
                    Dim max As Double = Double.MinValue
                    For Each ser As clsSeries In ActiveGraphTab.Series
                        With ser.ZedCurve
                            If .IsVisible Then
                                For i As Integer = 0 To .NPts - 1
                                    Dim y As Double = .Points(i).Y
                                    If y > 0 Then
                                        max = Math.Max(max, .Points(i).Y)
                                        min = Math.Min(min, .Points(i).Y)
                                    End If
                                Next
                            End If
                        End With
                    Next
                    If min <> Double.MaxValue Then
                        Dim _AxisExtra As structAxisExtra = AxisExtra(_Axis.Tag)
                        If _AxisExtra.AutoMinLog Then
                            .Min = Math.Pow(10, Math.Floor(Math.Log10(min)))
                            .MinAuto = False
                            _AxisExtra.AutoMinLog = True
                        End If
                        If _AxisExtra.AutoMaxLog Then
                            .Max = Math.Pow(10, Math.Ceiling(Math.Log10(max)))
                            .MaxAuto = False
                            _AxisExtra.AutoMaxLog = True
                        End If
                        _Axis.Tag = _AxisExtra
                    End If
                End If
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Set the maximum value for the x axis
    ''' </summary>
    <DisplayName("5. Maximum Value"), Category("Scale"), Description("Set the maximum value for the axis if Auto Scale is false")> _
    Public Property Max() As String
        Get
            If _Axis.Type = ZedGraph.AxisType.Date Or _Axis.Type = ZedGraph.AxisType.DateDual Then
                Return Date.FromOADate(_Axis.Scale.Max).ToString(MyDateTimeFormat)
            ElseIf _Axis.Type = ZedGraph.AxisType.DateAsOrdinal Then
                Return Date.FromOADate(_Axis.Scale.Min).DayOfYear
            Else
                Return Math.Round(_Axis.Scale.Max, 3)
            End If
        End Get
        Set(ByVal value As String)
            With _Axis
                SetAxisLimit(value, .Type, .Scale.MaxAuto, .Scale.Max)
                ResetLimitMinMax()
            End With
        End Set
    End Property

    ''' <summary>
    ''' Set the minimum limit value for the axis
    ''' </summary>
    <DisplayName("6. Maximum Limit"), Category("Scale"), Description("Set the maximum limit value for the axis; used by Zoom Limits (read-only; automatically set each time you manually set the axis min/max)"), [ReadOnly](True)> _
    Public Property MaxLimit() As String
        Get
            With AxisExtra(_Axis.Tag)
                If _Axis.Type = ZedGraph.AxisType.Date Or _Axis.Type = ZedGraph.AxisType.DateDual Then
                    If IsDate(.MaxLimit) Then
                        Return CDate(.MaxLimit).ToString(MyDateTimeFormat)
                    Else
                        Return "Not Set"
                    End If
                ElseIf _Axis.Type = ZedGraph.AxisType.DateAsOrdinal Then
                    If IsNumeric(.MinLimit) AndAlso Math.Abs(Val(.MinLimit)) < 1.0E+300 Then
                        Return Date.FromOADate(_Axis.Scale.Min).DayOfYear
                    Else
                        Return "Not Set"
                    End If
                Else
                    If IsNumeric(.MaxLimit) AndAlso Math.Abs(Val(.MaxLimit)) < 1.0E+300 Then
                        Return Math.Round(Val(.MaxLimit), 3)
                    Else
                        Return "Not Set"
                    End If
                End If
            End With
        End Get
        Set(ByVal value As String)
            Dim _AxisExtra As structAxisExtra = AxisExtra(_Axis.Tag)
            _AxisExtra.MaxLimit = value
            _Axis.Tag = _AxisExtra
            If _Axis.IsVisible Then ActiveGraphTab.ResetYAxes()
        End Set
    End Property

    Private Sub ResetLimitMinMax()
        Try
            With _Axis
                Dim _AxisExtra As clsAxis.structAxisExtra = clsAxis.AxisExtra(.Tag)
                If .Type = ZedGraph.AxisType.Date Or .Type = ZedGraph.AxisType.DateDual Then
                    If Not .Scale.MinAuto Then _AxisExtra.MinLimit = Date.FromOADate(.Scale.Min).ToString(MyDateTimeFormat)
                    If Not .Scale.MaxAuto Then _AxisExtra.MaxLimit = Date.FromOADate(.Scale.Max).ToString(MyDateTimeFormat)
                Else
                    If Not .Scale.MinAuto Then _AxisExtra.MinLimit = .Scale.Min
                    If Not .Scale.MaxAuto Then _AxisExtra.MaxLimit = .Scale.Max
                End If
                .Tag = _AxisExtra
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Reverse the scale?
    ''' </summary>
    <DisplayName("7. Reverse Scale?"), Category("Scale"), Description("Should scale be reversed (e.g., high values to low values)?")> _
    Public Property Reverse() As Boolean
        Get
            Return _Axis.Scale.IsReverse
        End Get
        Set(ByVal value As Boolean)
            _Axis.Scale.IsReverse = value
        End Set
    End Property
#End Region

End Class


''' <summary>
''' This class was created to store and display graph options in the properties grid
''' </summary>
<DefaultProperty("GraphTitle")> _
Friend Class clsGraphOptions

    Private _AutoGraphTitle As Boolean
    Private _NoteVisible As Boolean = True
    Private _NotePosition As enumNotePosition = enumNotePosition.TopRight
    Private _NoteAlignment As enumNoteAlignment = enumNoteAlignment.Center
    Private _NoteBorder As Boolean = True
    Private _Notes As String = ""
    Private _TitleFont As Font
    Private _LegendFont As Font
    Private _NoteFont As Font
    Friend Zed As ZedGraph.ZedGraphControl
    Private _ZoomOption As enumZoomOptions
    Private _FontScaleFactor As Double = 1.0
    Friend DefaultSeriesColor(1399) As Color
    Friend DefaultSeriesFormats As New Generic.List(Of clsSeries)

    Friend Enum enumLineType
        Auto = -2
        None
        Solid
        Dash
        Dot
        DashDot
        DashDotDot
        Bars
    End Enum

    ''' <summary>
    ''' Sets default values for new instance
    ''' </summary>
    ''' <param name="Zed">ZedGraph control that is already on form</param>
    Friend Sub New(ByRef Zed As ZedGraph.ZedGraphControl)
        Me.Zed = Zed
        Zed.GraphPane.IsFontsScaled = False
        Zed.GraphPane.IsPenWidthScaled = False
        'cycle standard series colors over the 15 standard VB colors
        For i As Integer = 0 To DefaultSeriesColor.Length - 1
            DefaultSeriesColor(i) = Choose((i Mod 14) + 1, Color.Black, Color.Red, Color.Blue, Color.Green, Color.DarkTurquoise, Color.Magenta, Color.Orange,
                                                           Color.Gray, Color.DarkRed, Color.DarkBlue, Color.DarkGreen, Color.DarkCyan, Color.DarkMagenta, Color.SaddleBrown)
        Next
        Reset()
    End Sub

    ''' <summary>
    ''' Reset to program defaults
    ''' </summary>
    ''' <remarks></remarks>
    Friend Sub Reset()
        Try
            ZoomOption = GetSetting(REGAPP, "GraphOptions", "ZoomOption", enumZoomOptions.Auto)
            ShowPoints = GetSetting(REGAPP, "GraphOptions", "ShowPoints", True)
            ScrollBars = GetSetting(REGAPP, "GraphOptions", "Scrollbars", False)

            GraphTitle = ""
            AutoGraphTitle = True
            TitleFont = New Font("Tahoma", 10, FontStyle.Bold, GraphicsUnit.Point)
            'GraphBorder = False
            LegendFont = New Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point)
            LegendVisible = True
            LegendPos = ZedGraph.LegendPos.BottomCenter
            LegendBorder = False
            FillColor = SystemColors.Info
            NoteAlignment = enumNoteAlignment.Center
            NoteBorder = True
            NotePosition = enumNotePosition.TopRight
            NoteText = ""
            NoteFont = New Font("Tahoma", 8, FontStyle.Regular, GraphicsUnit.Point)
            NoteVisible = True
            FontScaleFactor = 1.4

            'With Zed.GraphPane
            '    For xy As Integer = 1 To 2 'primary and secondary (e.g., left/right)
            '        With Choose(xy, .XAxis, .X2Axis)
            '            clsAxis.AxisExtra(.tag).Initialize()
            '        End With
            '        For i As Integer = 0 To 4
            '            With Choose(xy, .YAxisList(i), .Y2AxisList(i))
            '                clsAxis.AxisExtra(.Tag).Initialize()
            '            End With
            '        Next
            '    Next
            'End With

            LineType = enumLineType.Auto
            LineWidth = 1.0
            SymbolSize = 4
            SymbolFill = True

            ShowPoints = True
            With Zed
                .PointDateFormat = MyDateTimeFormat()
                .PointValueFormat = "N3"
                .GraphPane.IsBoundedRanges = False
                .IsAutoScrollRange = False
                .ScrollMinX = .GraphPane.XAxis.Scale.Min
                .ScrollMaxX = .GraphPane.XAxis.Scale.Max
                .ScrollMinY = .GraphPane.YAxis.Scale.Min
                .ScrollMaxY = .GraphPane.YAxis.Scale.Max
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

#Region "General Properties"

    ''' <summary>
    ''' Graph title (Zed.GraphPane.Title.Text)
    ''' </summary>
    <DisplayName("1. Auto graph title"), Category("General"), Description("If true will automatically set the graph title depending on what data are displayed")> _
    Public Property AutoGraphTitle() As Boolean
        Get
            Return _AutoGraphTitle
        End Get
        Set(ByVal value As Boolean)
            _AutoGraphTitle = value
            If _AutoGraphTitle And ActiveGraphTab() IsNot Nothing Then
                ActiveGraphTab.SetGraphTitle()
            End If
        End Set
    End Property

    ''' <summary>
    ''' Graph title (Zed.GraphPane.Title.Text)
    ''' </summary>
    <DisplayName("2. Graph title"), Category("General"), Description("Sets the graph title which will appear centered at the top of the graph")> _
    Public Property GraphTitle() As String
        Get
            Return Zed.GraphPane.Title.Text
        End Get
        Set(ByVal value As String)
            If value <> "" Then
                Zed.GraphPane.Title.Text = value
                Zed.GraphPane.Title.IsVisible = True
                AutoGraphTitle = False
            End If
        End Set
    End Property

    ''' <summary>
    ''' Graph title font (Zed.GraphPane.Title.FontSpec)
    ''' </summary>
    <DisplayName("3. Title font"), Category("General"), Description("Sets the font for the graph title")> _
    Public Property TitleFont() As Font
        Get
            Return _TitleFont
        End Get
        Set(ByVal value As Font)
            'round font sizes to integer since dialog only lets you select integers
            _TitleFont = New Font(value.FontFamily, Math.Round(value.Size, 0), value.Style, GraphicsUnit.Point)
            Zed.GraphPane.Title.FontSpec = GetFont(_TitleFont, Zed.GraphPane.Title.FontSpec, FontScaleFactor)
        End Set
    End Property

    ''' <summary>
    ''' Graph background color (solid fill) (Zed.GraphPane.Chart.Fill.Color)
    ''' </summary>
    <DisplayName("4. Background color"), Category("General"), Description("Sets the graph background color")> _
    Public Property FillColor() As Color
        Get
            Return Zed.GraphPane.Chart.Fill.Color
        End Get
        Set(ByVal value As Color)
            Zed.GraphPane.Chart.Fill.Color = value
            Zed.GraphPane.Chart.Fill.Type = ZedGraph.FillType.Solid
        End Set
    End Property

    ' ''' <summary>
    ' ''' Graph border (Zed.MasterPane.Border.IsVisible)
    ' ''' </summary>
    '<DisplayName("5. Graph border is visible?"), Category("General"), Description("Indicates if border is visible for graph. This is most important for printed and exported graphs.")> _
    'Public Property GraphBorder() As Boolean
    '    Get
    '        Return Zed.MasterPane.Border.IsVisible
    '    End Get
    '    Set(ByVal value As Boolean)
    '        Zed.MasterPane.Border.IsVisible = value
    '        Zed.Refresh()
    '    End Set
    'End Property

    ''' <summary>
    ''' FontScaleFactor
    ''' </summary>
    <DisplayName("5. Apply screen font scale factor?"), Category("General"), Description("Set to true to enforce screen font size fidelity to printed output. Use false for legacy graphs.")> _
    Public Property UseFontScaleFactor() As Boolean
        Get
            Return FontScaleFactor <> 1.0
        End Get
        Set(ByVal value As Boolean)
            If value Then
                FontScaleFactor = 96.0 / 72.0
            Else
                FontScaleFactor = 1.0
            End If
        End Set
    End Property

    Friend Property FontScaleFactor As Double
        Get
            Return _FontScaleFactor
        End Get
        Set(value As Double)
            _FontScaleFactor = value
            'force all zed font sizes to be recalculated and refreshed
            TitleFont = _TitleFont
            LegendFont = _LegendFont
            NoteFont = _NoteFont
            For i As Integer = 1 To 2
                Dim axis As New clsAxis(Zed, Choose(i, clsAxis.enumAxis.XAxis, clsAxis.enumAxis.X2Axis), 0, _FontScaleFactor)
                axis.TitleFont = axis.TitleFont
                axis.LabelFont = axis.LabelFont
                For j As Integer = 0 To 4
                    If j <= Zed.GraphPane.YAxisList.Count - 1 Then
                        axis = New clsAxis(Zed, Choose(i, clsAxis.enumAxis.YAxis, clsAxis.enumAxis.Y2Axis), j, _FontScaleFactor)
                        axis.TitleFont = axis.TitleFont
                        axis.LabelFont = axis.LabelFont
                    End If
                Next
            Next
        End Set
    End Property

    ''' <summary>
    ''' Show point coordinates when you hover over a point? (Zed.GraphPane.IsShowPointValues)
    ''' </summary>
    <DisplayName("6. Show point values?"), Category("General"), Description("When true, point values are shown as a tooltip when you hover over them. HOWEVER, you will not be able to right-click on series to hide them.")> _
    Public Property ShowPoints() As Boolean
        Get
            Return Zed.IsShowPointValues
        End Get
        Set(ByVal value As Boolean)
            Zed.IsShowPointValues = value
        End Set
    End Property

    ' '''' <summary>
    ' '''' Should the fonts and lines be scaled as the graph is resized? (Zed.GraphPane.IsFontsScaled)
    ' '''' </summary>
    '<DisplayName("5. Scale symbols and fonts?"), Category("General"), Description("Should the fonts and lines be scaled as the graph is resized?")> _
    'Public Property GraphIsScaled() As Boolean
    '    Get
    '        Return Zed.GraphPane.IsFontsScaled
    '    End Get
    '    Set(ByVal value As Boolean)
    '        With Zed.GraphPane
    '            .IsFontsScaled = value
    '            '.IsPenWidthScaled = value
    '            .IsPenWidthScaled = False
    '        End With
    '    End Set
    'End Property

    ' '''' <summary>
    ' '''' Set the base dimension from which fonts and lines will be scaled
    ' '''' </summary>
    '<DisplayName("6. Base dimension for scaling"), Category("General"), Description("This sets 'normal' graph size (in inches) on which all scaling of symbols and fonts are based. For example, if the BaseDimension is 8.0 inches and the Title size is 14 points, the pane title font will be 14 points when the graph is approximately 8.0 inches wide, and 7 points when the graph is 4.0 inches wide.")> _
    'Public Property BaseDimension() As Double
    '    Get
    '        Return Zed.GraphPane.BaseDimension
    '    End Get
    '    Set(ByVal value As Double)
    '        Zed.GraphPane.BaseDimension = value
    '    End Set
    'End Property

    '''' <summary>
    '''' Should the yaxis and y2axis by synchronized to use the same major interval? (Zed.GraphPane.IsFontsScaled)
    '''' </summary>
    '<DisplayName("7. Synchronize y axes?"), Category("General"), Description("When autoscaled, should the left and right y axes min/max and grid spacing be adjusted so they are aligned?")> _
    'Public Property YAxesSynced() As Boolean
    '    Get
    '        Return Zed.GraphPane.IsAlignGrids
    '    End Get
    '    Set(ByVal value As Boolean)
    '        Zed.GraphPane.IsAlignGrids = value
    '        Zed.AxisChange()
    '        Zed.Refresh()
    '    End Set
    'End Property


#End Region

#Region "Legend and Notes Properties"

    ''' <summary>
    ''' Legend font (Zed.GraphPane.Title.FontSpec)
    ''' </summary>
    <DisplayName("1. Legend font"), Category("Legend"), Description("Sets the font for the legend")> _
    Public Property LegendFont() As Font
        Get
            Return _LegendFont
        End Get
        Set(ByVal value As Font)
            'round font sizes to integer since dialog only lets you select integers
            _LegendFont = New Font(value.FontFamily, Math.Round(value.Size, 0), value.Style, GraphicsUnit.Point)
            Zed.GraphPane.Legend.FontSpec = GetFont(_LegendFont, Zed.GraphPane.Legend.FontSpec, FontScaleFactor)
            SetNote()
        End Set
    End Property

    ''' <summary>
    ''' Is legend visible? (Zed.GraphPane.Legend.IsVisible)
    ''' </summary>
    <DisplayName("2. Legend order reversed?"), Category("Legend"), Description("If false, last series drawn (on top) is at top of list (legacy); if true order will be reversed")> _
    Public Property LegendReversed() As Boolean
        Get
            Return Zed.GraphPane.Legend.IsReverse
        End Get
        Set(ByVal value As Boolean)
            Zed.GraphPane.Legend.IsReverse = value
        End Set
    End Property

    ''' <summary>
    ''' Is legend visible? (Zed.GraphPane.Legend.IsVisible)
    ''' </summary>
    <DisplayName("3. Legend is visible?"), Category("Legend"), Description("Sets the visibility of the legend")> _
    Public Property LegendVisible() As Boolean
        Get
            Return Zed.GraphPane.Legend.IsVisible
        End Get
        Set(ByVal value As Boolean)
            Zed.GraphPane.Legend.IsVisible = value
        End Set
    End Property

    ''' <summary>
    ''' Legend position (Zed.GraphPane.Legend.Position)
    ''' </summary>
    <DisplayName("4. Legend position"), Category("Legend"), Description("Sets the position of the legend if visible")> _
    Public Property LegendPos() As ZedGraph.LegendPos
        Get
            Return Zed.GraphPane.Legend.Position
        End Get
        Set(ByVal value As ZedGraph.LegendPos)
            Zed.GraphPane.Legend.Position = value
            Zed.GraphPane.Legend.IsVisible = True
        End Set
    End Property

    ''' <summary>
    ''' Graph title font (Zed.GraphPane.Title.FontSpec)
    ''' </summary>
    <DisplayName("5. Legend border is visible?"), Category("Legend"), Description("Indicates if border is visible for legend.")> _
    Public Property LegendBorder() As Boolean
        Get
            Return Zed.GraphPane.Legend.Border.IsVisible
        End Get
        Set(ByVal value As Boolean)
            Zed.GraphPane.Legend.Border.IsVisible = value
        End Set
    End Property

    ''' <summary>
    ''' Arbitrary notes on graph
    ''' </summary>
    <DisplayName("1. Graph notes"), Category("Notes"), Description("Arbitrary notes to be superimposed on graph"), Editor("System.ComponentModel.Design.MultilineStringEditor", "System.Drawing.Design.UITypeEditor")> _
    Public Property NoteText() As String
        Get
            Return _Notes
        End Get
        Set(ByVal value As String)
            _Notes = value
            If _Notes <> "" And _NoteVisible Then
                _NotePosition = enumNotePosition.TopRight
                _NoteVisible = True
            End If
            SetNote()
        End Set
    End Property

    ''' <summary>
    ''' Graph title font (Zed.GraphPane.Title.FontSpec)
    ''' </summary>
    <DisplayName("2. Notes font"), Category("Notes"), Description("Sets the font for the graph notes")> _
    Public Property NoteFont() As Font
        Get
            Return _NoteFont
        End Get
        Set(ByVal value As Font)
            _NoteFont = value
            SetNote()
        End Set
    End Property

    ''' <summary>
    ''' Are notes visible? 
    ''' </summary>
    <DisplayName("3. Notes are visible?"), Category("Notes"), Description("Sets the visibility of graph notes")> _
    Public Property NoteVisible() As Boolean
        Get
            Return _NoteVisible
        End Get
        Set(ByVal value As Boolean)
            _NoteVisible = value
            SetNote()
        End Set
    End Property

    ''' <summary>
    ''' Note position
    ''' </summary>
    <DisplayName("4. Note position"), Category("Notes"), Description("Sets the position of the graph note if used")> _
    Public Property NotePosition() As enumNotePosition
        Get
            Return _NotePosition
        End Get
        Set(ByVal value As enumNotePosition)
            _NotePosition = value
            SetNote()
        End Set
    End Property

    ''' <summary>
    ''' Note text alignment
    ''' </summary>
    <DisplayName("5. Note text alignment"), Category("Notes"), Description("Sets the alignment of the text contained in the graph note if used")> _
    Public Property NoteAlignment() As enumNoteAlignment
        Get
            Return _NoteAlignment
        End Get
        Set(ByVal value As enumNoteAlignment)
            _NoteAlignment = value
            SetNote()
        End Set
    End Property

    ''' <summary>
    ''' Note border
    ''' </summary>
    <DisplayName("6. Note border is visible?"), Category("Notes"), Description("If true, a solid border will be drawn around the graph note (and the background will be filled).")> _
    Public Property NoteBorder() As Boolean
        Get
            Return _NoteBorder
        End Get
        Set(ByVal value As Boolean)
            _NoteBorder = value
            SetNote()
        End Set
    End Property

    Private Sub SetNote()
        'remove any prior object
        For Each obj As ZedGraph.GraphObj In Zed.GraphPane.GraphObjList
            If TypeOf obj Is ZedGraph.TextObj AndAlso obj.Tag = "Notes" Then
                Zed.GraphPane.GraphObjList.Remove(obj)
                Exit For
            End If
        Next

        If Not _NoteVisible Then Exit Sub

        'if non empty, add a new one
        If _Notes <> "" And _NoteVisible Then
            Dim obj As New ZedGraph.TextObj()
            With obj
                .Text = _Notes.Replace("\n", vbCrLf).Replace("\t", "")
                .Tag = "Notes"
                .FontSpec = GetFont(_NoteFont, .FontSpec, FontScaleFactor)
                .FontSpec.StringAlignment = Choose(_NoteAlignment + 1, StringAlignment.Near, StringAlignment.Center, StringAlignment.Far)
                If _NoteBorder Then
                    .FontSpec.Fill = New ZedGraph.Fill(Color.White)
                    .FontSpec.Border.IsVisible = True
                Else
                    .FontSpec.Fill = New ZedGraph.Fill(Color.Transparent)
                    .FontSpec.Border.IsVisible = False
                End If
                Select Case _NotePosition
                    Case enumNotePosition.TopLeft
                        .Location = New ZedGraph.Location(0.02, 0.02, ZedGraph.CoordType.ChartFraction, ZedGraph.AlignH.Left, ZedGraph.AlignV.Top)
                    Case enumNotePosition.TopCenter
                        .Location = New ZedGraph.Location(0.5, 0.02, ZedGraph.CoordType.ChartFraction, ZedGraph.AlignH.Center, ZedGraph.AlignV.Top)
                    Case enumNotePosition.TopRight
                        .Location = New ZedGraph.Location(0.98, 0.02, ZedGraph.CoordType.ChartFraction, ZedGraph.AlignH.Right, ZedGraph.AlignV.Top)
                    Case enumNotePosition.BottomLeft
                        .Location = New ZedGraph.Location(0.02, 0.98, ZedGraph.CoordType.ChartFraction, ZedGraph.AlignH.Left, ZedGraph.AlignV.Bottom)
                    Case enumNotePosition.BottomCenter
                        .Location = New ZedGraph.Location(0.5, 0.98, ZedGraph.CoordType.ChartFraction, ZedGraph.AlignH.Center, ZedGraph.AlignV.Bottom)
                    Case enumNotePosition.BottomRight
                        .Location = New ZedGraph.Location(0.98, 0.98, ZedGraph.CoordType.ChartFraction, ZedGraph.AlignH.Right, ZedGraph.AlignV.Bottom)
                End Select
            End With
            Zed.GraphPane.GraphObjList.Add(obj)
            Zed.Refresh()
        End If
    End Sub

#End Region

#Region "Panning and Zooming Properties"

    ''' <summary>
    ''' Is legend visible? (Zed.GraphPane.Legend.IsVisible)
    ''' </summary>
    <DisplayName("1. Horizontal/vertical zoom and pan"), Category("Panning and Zooming"), Description("Is panning and zooming allowed? Auto means mode automatically changes depending on where you first click on graph. Note: zoom by rolling mouse wheel; pan by pressing and holding it.")> _
    Public Property ZoomOption() As enumZoomOptions
        Get
            Return _ZoomOption
        End Get
        Set(ByVal value As enumZoomOptions)
            _ZoomOption = value
            If value <> enumZoomOptions.Auto Then
                With Zed
                    .IsEnableHPan = (value = enumZoomOptions.Horizontal Or value = enumZoomOptions.Both)
                    .IsEnableHZoom = .IsEnableHPan
                    .IsEnableVPan = (value = enumZoomOptions.Vertical Or value = enumZoomOptions.Both)
                    .IsEnableVZoom = .IsEnableVPan
                End With
            End If
        End Set
    End Property

    ''' <summary>
    ''' Scrollbars visible? (Zed.GraphPane.Legend.IsVisible)
    ''' </summary>
    <DisplayName("2. Display scroll bars?"), Category("Panning and Zooming"), Description("If true, horizontal and vertical scroll bars appear to help you pan in the graph. This is global for all graph tabs.")> _
    Public Property ScrollBars() As Boolean
        Get
            Return Zed.IsShowHScrollBar
        End Get
        Set(ByVal value As Boolean)
            If Zed.InvokeRequired Then
                Zed.BeginInvoke(Sub()
                                    Zed.IsShowHScrollBar = value
                                    Zed.IsShowVScrollBar = value
                                End Sub)
            Else
                Zed.IsShowHScrollBar = value
                Zed.IsShowVScrollBar = value
            End If
        End Set
    End Property

#End Region

#Region "Series Properties"

    <DisplayName("1. Line Type"), Category("Series Line and Symbol Default Formats"), Description("Default line type for newly added series; if auto, then line type depends on data source. May be overridden by saved default series formats.")> _
    Public Property LineType() As enumLineType

    <DisplayName("2. Line Width"), Category("Series Line and Symbol Default Formats"), Description("Default line width for newly added series. May be overridden by saved default series formats.")> _
    Public Property LineWidth As Single

    <DisplayName("3. Symbol Size"), Category("Series Line and Symbol Default Formats"), Description("Default symbol size for newly added series. May be overridden by saved default series formats.")> _
    Public Property SymbolSize As Single

    <DisplayName("4. Solid Fill?"), Category("Series Line and Symbol Default Formats"), Description("Default symbol fill setting for newly added series. May be overridden by saved default series formats.")> _
    Public Property SymbolFill As Boolean

#End Region
End Class

''' <summary>
''' This class contains all the properties associated with each graph tab
''' </summary>
Friend Class clsGraphTab
    Implements IDisposable

    Friend Enum enumDrawMode
        None
        FirstPoint
        SecondPoint
    End Enum

    Friend Enum enumDrawType
        Arrow
        Line
        Box
        Ellipse
        Textbox
        RedrawTextbox
    End Enum

    Friend DrawMode As enumDrawMode
    Friend DrawType As enumDrawType
    Friend DrawColor As Color = Color.Black
    Friend DrawWidth As Integer = 0 'width in points
    Friend Const DrawArrowSize As Integer = 12
    Private DrawPt1 As Point

#Region " IDisposable Support "
    Private disposedValue As Boolean = False        ' To detect redundant calls

    ' This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    ' IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            Zed.GraphPane.CurveList.Clear()
            _GraphOptions = Nothing
            _Series.Clear()
            _Series = Nothing
        End If
        Me.disposedValue = True
    End Sub
#End Region

#Region "Properties"

    ''' <summary>
    ''' The current animation date-time setting
    ''' </summary>
    Friend Property AnimationInfo() As clsAnimationInfo

    Private _GraphOptions As clsGraphOptions

    Friend ReadOnly Property GraphOptions() As clsGraphOptions
        Get
            Return _GraphOptions
        End Get
    End Property

    ''' <summary>
    ''' Type of graph to display
    ''' </summary>
    Friend Property GraphType() As enumGraphType

    Private Delegate Sub stringDelegate(s As String)

    Private _Name As String

    Friend Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            Dim OldName As String = _Name
            _Name = value
            Dim SelectedTab As TabPage = Nothing
            For Each tp As TabPage In GraphForm.TabGraph.TabPages
                If tp.Text = OldName Then SelectedTab = tp : Exit For
            Next
            If SelectedTab Is Nothing Then Exit Property
            If GraphForm.TabGraph.InvokeRequired Then
                GraphForm.TabGraph.Invoke(Sub()
                                              SelectedTab.Text = _Name
                                          End Sub)
            Else
                SelectedTab.Text = _Name
            End If
        End Set
    End Property

    ''' <summary>
    ''' Indicate whether longitudinal profile should be plotted versus river mile or segment number
    ''' </summary>
    Friend Property ProfileXPlot() As enumProfileXPlot

    Friend Property Series() As Generic.List(Of clsSeries)

    Private WithEvents _Zed As ZedGraph.ZedGraphControl

    Friend ReadOnly Property Zed() As ZedGraph.ZedGraphControl
        Get
            Return _Zed
        End Get
    End Property
#End Region

#Region "Zed Routines"

    Private SelectedAxis As ZedGraph.Axis
    Private SelectedAxisIndex As Integer
    Private SelectedCurveIndex As Integer
    Dim NearestObject As Object

    Private Sub Zed_CursorChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles _Zed.CursorChanged
        'Debug.Print(Zed.Cursor.ToString)
    End Sub

    Private Sub Zed_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles _Zed.KeyPress
        If e.KeyChar = Chr(27) Then
            DrawMode = enumDrawMode.None
            Zed.Cursor = Cursors.Arrow
            Zed.IsEnableZoom = True
            GraphForm.Statusbar.Text = "Draw cancelled"
        End If
    End Sub

    Private Sub Zed_MouseDoubleClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles _Zed.MouseDoubleClick
        Try
            'depending on type of object that was double-clicked, perform action:
            'axes: change axis title
            'legend: make invisible
            'graph title: change it
            'in chart window: manage series
            'elsewhere: graph options

            With Zed.GraphPane
                Dim Index As Integer
                If Zed.GraphPane.FindNearestObject(New PointF(e.X, e.Y), Zed.CreateGraphics, NearestObject, Index) AndAlso Not TypeOf NearestObject Is ZedGraph.LineItem Then
                    If TypeOf NearestObject Is ZedGraph.XAxis Then
                        PromptTitle("X Axis", .XAxis.Title.Text, .XAxis)
                    ElseIf TypeOf NearestObject Is ZedGraph.X2Axis Then
                        PromptTitle("X Axis", .X2Axis.Title.Text, .X2Axis)
                    ElseIf TypeOf NearestObject Is ZedGraph.YAxis Then
                        PromptTitle("Y Axis", .YAxisList(Index).Title.Text, .YAxisList(Index))
                    ElseIf TypeOf NearestObject Is ZedGraph.Y2Axis Then
                        PromptTitle("Y Axis", .Y2AxisList(Index).Title.Text, .Y2AxisList(Index))
                    ElseIf TypeOf NearestObject Is ZedGraph.Legend Then
                        .Legend.IsVisible = False
                    ElseIf TypeOf NearestObject Is ZedGraph.GraphPane Then
                        PromptTitle("Graph", GraphOptions.GraphTitle, Nothing)
                    End If
                    Zed.Refresh()
                Else
                    Dim x As Double = .XAxis.Scale.ReverseTransform(e.X)
                    Dim y As Double = .YAxis.Scale.ReverseTransform(e.Y)
                    If x >= .XAxis.Scale.Min And x <= .XAxis.Scale.Max And y >= .YAxis.Scale.Min And y <= .YAxis.Scale.Max Then
                        GraphForm.ManageSeries(False)
                    Else
                        With New frmOptions()
                            .TabControl1.SelectedIndex = 1
                            .ShowDialog(GraphForm)
                        End With
                    End If
                End If
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub PromptTitle(ByVal TitleType As String, ByRef Text As String, ByRef Axis As ZedGraph.Axis)
        Try
            Dim s As String = InputBox(String.Format("Enter the new {0} title:", TitleType), "Enter New Title", Text)
            If s <> "" Then
                Text = s
                If Axis IsNot Nothing Then
                    Dim AxisExtra As clsAxis.structAxisExtra = clsAxis.AxisExtra(Axis.Tag)
                    AxisExtra.AutoTitle = False
                    Axis.Tag = AxisExtra
                End If
            End If
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub Zed_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles _Zed.MouseLeave
        If GraphForm IsNot Nothing Then GraphForm.Statusbar.Text = ""
    End Sub

    Private Function Zed_MouseDownEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal e As System.Windows.Forms.MouseEventArgs) As Boolean Handles _Zed.MouseDownEvent
        Try
            Dim DrawPt2 As Point
            Select Case DrawMode
                Case enumDrawMode.FirstPoint
                    DrawPt1 = e.Location
                    Select Case DrawType
                        Case enumDrawType.Textbox, enumDrawType.RedrawTextbox
                            Dim x1, y1 As Double
                            GetChartFraction(DrawPt1, x1, y1)
                            Dim graphObj As ZedGraph.GraphObj = Nothing
                            Select Case DrawType
                                Case enumDrawType.Textbox
                                    Dim s As String = frmInputBox.ShowInputBox("Enter the desired text you desire; it will be placed as a single line, centered in the box just drawn:", "Draw Textbox")
                                    If s = "" Then
                                        Return False
                                    Else
                                        graphObj = New ZedGraph.TextObj(s, x1, y1, CoordType.ChartFraction, AlignH.Left, AlignV.Top)
                                    End If
                                Case enumDrawType.RedrawTextbox
                                    graphObj = New ZedGraph.TextObj(CType(NearestObject, ZedGraph.TextObj).Text, x1, y1, CoordType.ChartFraction, AlignH.Left, AlignV.Top)
                            End Select
                            graphObj.Location.CoordinateFrame = CoordType.ChartFraction
                            Zed.GraphPane.GraphObjList.Insert(0, graphObj)

                            Zed.Refresh()
                            DrawMode = enumDrawMode.None
                            Zed.Cursor = Cursors.Arrow
                            Zed.IsEnableZoom = True
                            GraphForm.Statusbar.Text = ""

                        Case Else
                            DrawMode = enumDrawMode.SecondPoint
                    End Select

                Case enumDrawMode.SecondPoint
                    DrawPt2 = e.Location
                    Dim x1, y1, x2, y2 As Double
                    GetChartFraction(DrawPt1, x1, y1)
                    GetChartFraction(DrawPt2, x2, y2)
                    With Zed.GraphPane
                        '.ReverseTransform(DrawPt1, x1, y1) 'convert to user units
                        '.ReverseTransform(DrawPt2, x2, y2)
                        ''convert to percent screen
                        'With .XAxis.Scale
                        '    x1 = (x1 - .Min) / (.Max - .Min)
                        '    x2 = (x2 - .Min) / (.Max - .Min)
                        'End With
                        'With .YAxis.Scale
                        '    If .IsLog Then
                        '        y1 = (Math.Log(.Max) - Math.Log(y1)) / (Math.Log(.Max) - Math.Log(.Min))
                        '        y2 = (Math.Log(.Max) - Math.Log(y2)) / (Math.Log(.Max) - Math.Log(.Min))
                        '    Else
                        '        y1 = (.Max - y1) / (.Max - .Min)
                        '        y2 = (.Max - y2) / (.Max - .Min)
                        '    End If
                        '    If .IsReverse Then
                        '        y1 = 1.0 - y1
                        '        y2 = 1.0 - y2
                        '    End If
                        'End With
                        Dim graphObj As ZedGraph.GraphObj = Nothing
                        Select Case DrawType
                            Case enumDrawType.Arrow
                                graphObj = New ZedGraph.ArrowObj(ActiveGraphTab.DrawColor, Math.Max(clsGraphTab.DrawArrowSize, ActiveGraphTab.DrawWidth * 4), x1, y1, x2, y2)
                                CType(graphObj, ArrowObj).Line.Width = ActiveGraphTab.DrawWidth
                            Case enumDrawType.Line
                                graphObj = New ZedGraph.LineObj(ActiveGraphTab.DrawColor, x1, y1, x2, y2)
                                CType(graphObj, LineObj).Line.Width = ActiveGraphTab.DrawWidth
                            Case enumDrawType.Box
                                graphObj = New ZedGraph.BoxObj(Math.Min(x1, x2), Math.Min(y1, y2), Math.Abs(x2 - x1), Math.Abs(y2 - y1), ActiveGraphTab.DrawColor, Color.Transparent)
                                CType(graphObj, BoxObj).Border.Width = ActiveGraphTab.DrawWidth
                            Case enumDrawType.Ellipse
                                graphObj = New ZedGraph.EllipseObj(Math.Min(x1, x2), Math.Min(y1, y2), Math.Abs(x2 - x1), Math.Abs(y2 - y1), ActiveGraphTab.DrawColor, Color.Transparent)
                                CType(graphObj, EllipseObj).Border.Width = ActiveGraphTab.DrawWidth
                                'Case enumDrawType.Textbox
                                '    Dim s As String = frmInputBox.ShowInputBox("Enter the text you desire; it will be placed as a single line, centered in the box just drawn:", "Draw Textbox")
                                '    If s = "" Then
                                '        Return False
                                '    Else
                                '        graphObj = New ZedGraph.TextObj(s, x1, y1, CoordType.ChartFraction, AlignH.Left, AlignV.Top)
                                '        'cannot set line color or width
                                '        'With CType(graphObj, ZedGraph.TextObj)
                                '        '    .FontSpec = Zed.GraphPane.Legend.FontSpec
                                '        'End With
                                '    End If
                                'Case enumDrawType.RedrawTextbox
                                '    graphObj = New ZedGraph.TextObj(CType(NearestObject, ZedGraph.TextObj).Text, x1, y1, CoordType.ChartFraction, AlignH.Left, AlignV.Top)
                        End Select
                        graphObj.Location.CoordinateFrame = CoordType.ChartFraction
                        .GraphObjList.Insert(0, graphObj)
                    End With

                    Zed.Refresh()
                    DrawMode = enumDrawMode.None
                    Zed.Cursor = Cursors.Arrow
                    Zed.IsEnableZoom = True
                    GraphForm.Statusbar.Text = ""
                Case Else
                    With Zed.GraphPane
                        Dim Index As Integer
                        If Zed.GraphPane.FindNearestObject(New PointF(e.X, e.Y), Zed.CreateGraphics, NearestObject, Index) Then
                            If TypeOf NearestObject Is ZedGraph.XAxis Then
                                GraphForm.tabProperties.SelectedIndex = 2
                                GraphForm.cboAxis.SelectedIndex = 0
                                GraphForm.SetAxisProperties()
                            ElseIf TypeOf NearestObject Is ZedGraph.X2Axis Then
                                GraphForm.tabProperties.SelectedIndex = 2
                                GraphForm.cboAxis.SelectedIndex = 1
                                GraphForm.SetAxisProperties()
                            ElseIf TypeOf NearestObject Is ZedGraph.YAxis Then
                                GraphForm.tabProperties.SelectedIndex = 2
                                GraphForm.cboAxis.SelectedIndex = 2
                                GraphForm.SetAxisProperties()
                            ElseIf TypeOf NearestObject Is ZedGraph.Y2Axis Then
                                GraphForm.tabProperties.SelectedIndex = 2
                                GraphForm.cboAxis.SelectedIndex = 3
                                GraphForm.SetAxisProperties()
                            ElseIf TypeOf NearestObject Is ZedGraph.Legend Then
                                GraphForm.tabProperties.SelectedIndex = 1
                            ElseIf TypeOf NearestObject Is ZedGraph.GraphPane Then
                                GraphForm.tabProperties.SelectedIndex = 1
                            ElseIf TypeOf NearestObject Is ZedGraph.LineItem Then
                                GraphForm.tabProperties.SelectedIndex = 0
                                GraphForm.lstSeries.SelectedIndex = Math.Min(GraphForm.lstSeries.Items.Count - 1, .CurveList.Count - 1 - .CurveList.IndexOf(NearestObject))
                            End If
                        End If

                        If GraphOptions.ZoomOption = enumZoomOptions.Auto Then
                            'set desired zoom mode depending on where user clicked

                            Dim x1, y1 As Double
                            .ReverseTransform(e.Location, x1, y1)
                            'convert to percent screen
                            With .XAxis.Scale
                                x1 = (x1 - .Min) / (.Max - .Min)
                            End With
                            With .YAxis.Scale
                                If .IsLog Then
                                    y1 = (Math.Log(y1) - Math.Log(.Min)) / (Math.Log(.Max) - Math.Log(.Min))
                                Else
                                    y1 = (y1 - .Min) / (.Max - .Min)
                                End If
                            End With
                            If (y1 >= 0 And y1 < 0.1) Or (y1 <= 1 And y1 > 0.9) Then
                                Zed.IsEnableHZoom = True
                                Zed.IsEnableHPan = True
                                Zed.IsEnableVZoom = False
                                Zed.IsEnableVPan = False
                            ElseIf (x1 >= 0 And x1 < 0.1) Or (x1 <= 1 And x1 > 0.9) Then
                                Zed.IsEnableHZoom = False
                                Zed.IsEnableHPan = False
                                Zed.IsEnableVZoom = True
                                Zed.IsEnableVPan = True
                            ElseIf x1 < 1.0 And y1 < 1.0 Then
                                Zed.IsEnableHZoom = True
                                Zed.IsEnableHPan = True
                                Zed.IsEnableVZoom = True
                                Zed.IsEnableVPan = True
                            End If
                        End If
                    End With
            End Select
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try

    End Function

    Private Sub GetChartFraction(pt As Point, ByRef x As Double, ByRef y As Double)
        With Zed.GraphPane
            .ReverseTransform(pt, x, y) 'convert to user units
            'convert to percent screen
            With .XAxis.Scale
                x = (x - .Min) / (.Max - .Min)
            End With
            With .YAxis.Scale
                If .IsLog Then
                    y = (Math.Log(.Max) - Math.Log(y)) / (Math.Log(.Max) - Math.Log(.Min))
                Else
                    y = (.Max - y) / (.Max - .Min)
                End If
                If .IsReverse Then
                    y = 1.0 - y
                End If
            End With
        End With
    End Sub

    ''' <summary>
    ''' Add some WRDB items to context menu
    ''' </summary>
    Private Sub Zed_ContextMenuBuilder(ByVal sender As ZedGraph.ZedGraphControl, ByVal menuStrip As System.Windows.Forms.ContextMenuStrip, ByVal mousePt As System.Drawing.Point, ByVal objState As ZedGraph.ZedGraphControl.ContextMenuObjectState) Handles _Zed.ContextMenuBuilder
        Try
            'hide 'Set Scale to Default' item--it resets the axis format, etc., and others that don't behave like menu items
            For Each item As ToolStripItem In menuStrip.Items
                If ItemIn(item.Tag, "save_as", "set_default", "undo_all", "unzoom") Then
                    item.Visible = False
                ElseIf item.Tag = "copy" Then
                    item.Image = My.Resources.CopyHS
                ElseIf item.Tag = "page_setup" Then
                    item.Image = My.Resources.PrintSetupHS
                ElseIf item.Tag = "print" Then
                    item.Image = My.Resources.PrintHS
                    'ElseIf item.Tag = "save_as" Then
                    '    item.Image = My.Resources.saveHS
                ElseIf item.Tag = "show_val" Then
                    item.Image = My.Resources.ActualSizeHS
                End If
            Next

            Dim ZoomPrevMenu As New ToolStripMenuItem("Zoom Previous")
            Dim ZoomLimitsMenu As New ToolStripMenuItem("Zoom Limits")
            Dim ZoomAllMenu As New ToolStripMenuItem("Zoom All")

            Dim ZoomMenu As New ToolStripMenuItem("Zoom/Pan Mode")
            Dim ZoomHMenu As New ToolStripMenuItem("Horizontal")
            Dim ZoomVMenu As New ToolStripMenuItem("Vertical")
            Dim ZoomBMenu As New ToolStripMenuItem("Both")
            Dim ZoomAMenu As New ToolStripMenuItem("Auto")

            Dim ExcelMenu As New ToolStripMenuItem("Send to Excel...")
            Dim SendMenu As New ToolStripMenuItem("Send Image to...")
            Dim PDFMenu As New ToolStripMenuItem("Send to PDF document")
            Dim OptionsMenu As New ToolStripMenuItem("Graph Options...")
            Dim AxesMenu As New ToolStripMenuItem("Configure Axis")
            Dim ScaleMenu As New ToolStripMenuItem("Set Range from 0 to...")
            Dim ManageMenu As New ToolStripMenuItem("Manage Series...")
            Dim HideMenu As New ToolStripMenuItem("Hide Series")
            Dim ShowMenu As New ToolStripMenuItem("Show All Series")

            Dim DrawMenu As New ToolStripMenuItem("Edit Drawing Object")
            Dim DrawRedrawMenu As New ToolStripMenuItem("Redraw")
            Dim DrawColorMenu As New ToolStripMenuItem("Line Color...")
            Dim DrawWidthMenu As New ToolStripMenuItem("Line Width...")
            Dim DrawDeleteMenu As New ToolStripMenuItem("Delete")
            Dim DrawDeleteAllMenu As New ToolStripMenuItem("Delete All")
            Dim DrawHideAllMenu As New ToolStripMenuItem("Hide All")
            Dim DrawShowAllMenu As New ToolStripMenuItem("Show All")

            With ZoomPrevMenu
                .Image = My.Resources.ZoomPrev
                .ImageTransparentColor = Color.Fuchsia
                AddHandler .Click, AddressOf ZoomPrevious
            End With

            With ZoomLimitsMenu
                .Image = My.Resources.ZoomWin
                .ImageTransparentColor = Color.Silver
                AddHandler .Click, AddressOf ZoomLimits
            End With

            With ZoomAllMenu
                .Image = My.Resources.ZoomExtents
                .ImageTransparentColor = Color.Fuchsia
                AddHandler .Click, AddressOf ZoomExtents
            End With

            ZoomMenu.Image = My.Resources.ZoomHS

            With ZoomMenu.DropDownItems
                .Add(ZoomHMenu)
                .Add(ZoomVMenu)
                .Add(ZoomBMenu)
                .Add(ZoomAMenu)
            End With

            AddHandler ZoomBMenu.Click, AddressOf ZedZoom
            AddHandler ZoomHMenu.Click, AddressOf ZedZoom
            AddHandler ZoomVMenu.Click, AddressOf ZedZoom
            AddHandler ZoomAMenu.Click, AddressOf ZedZoom

            With GraphOptions
                ZoomAMenu.Checked = .ZoomOption = enumZoomOptions.Auto
                ZoomBMenu.Checked = .ZoomOption = enumZoomOptions.Both
                ZoomHMenu.Checked = .ZoomOption = enumZoomOptions.Horizontal
                ZoomVMenu.Checked = .ZoomOption = enumZoomOptions.Vertical
            End With

            With ExcelMenu
                .Image = My.Resources.Excel
                .ImageTransparentColor = Color.Fuchsia
                AddHandler .Click, AddressOf ZedExcel
            End With

            With SendMenu
                .Image = My.Resources.saveHS
                AddHandler .Click, AddressOf ZedSend
            End With

            With PDFMenu
                .Image = My.Resources.PDF
                AddHandler .Click, AddressOf ZedPDF
            End With

            With OptionsMenu
                .Image = My.Resources.PropertiesHS
                AddHandler .Click, AddressOf ZedOptions
            End With

            With AxesMenu
                .Image = My.Resources.GraphFormat
                .ImageTransparentColor = Color.Silver
                AddHandler .Click, AddressOf ZedAxes
            End With

            With ScaleMenu
                .Image = My.Resources.AlignObjectsTopHS
            End With
            AddHandler ScaleMenu.Click, AddressOf ZedScale

            With ManageMenu
                .Image = My.Resources.Tools
                .ImageTransparentColor = Color.Fuchsia
                AddHandler .Click, AddressOf ZedManage
            End With

            With HideMenu
                .Image = My.Resources.DeleteHS
                AddHandler .Click, AddressOf ZedHide
            End With

            With ShowMenu
                .Image = My.Resources.CheckBoxHS
                AddHandler .Click, AddressOf ZedShow
            End With

            With DrawMenu
                .Image = My.Resources.CommentHS
            End With

            With DrawColorMenu
                .Image = My.Resources.LineColorHS
            End With

            With DrawWidthMenu
                .Image = My.Resources.LineControl_10293_24
                .ImageTransparentColor = Color.Fuchsia
            End With

            With DrawDeleteMenu
                .Image = My.Resources.DeleteHS
            End With

            With DrawDeleteAllMenu
                .Image = My.Resources.DeleteFolderHS
            End With

            With DrawHideAllMenu
                .Image = My.Resources.ZoomOut
                .ImageTransparentColor = Color.Silver
                .ImageScaling = ToolStripItemImageScaling.None
            End With

            With DrawShowAllMenu
                .Image = My.Resources.ZoomIn
                .ImageTransparentColor = Color.Silver
                .ImageScaling = ToolStripItemImageScaling.None
            End With

            With DrawMenu.DropDownItems
                .Add(DrawRedrawMenu)
                .Add(DrawColorMenu)
                .Add(DrawWidthMenu)
                .Add(DrawDeleteMenu)
                .Add(DrawDeleteAllMenu)
                .Add(New ToolStripSeparator)
                .Add(DrawHideAllMenu)
                .Add(DrawShowAllMenu)
            End With

            AddHandler DrawRedrawMenu.Click, AddressOf DrawRedraw
            AddHandler DrawColorMenu.Click, AddressOf DrawColorReset
            AddHandler DrawWidthMenu.Click, AddressOf DrawWidthReset
            AddHandler DrawDeleteMenu.Click, AddressOf DrawDelete
            AddHandler DrawDeleteAllMenu.Click, AddressOf DrawDeleteAll
            AddHandler DrawHideAllMenu.Click, AddressOf DrawHideAll
            AddHandler DrawShowAllMenu.Click, AddressOf DrawShowAll

            NearestObject = Nothing
            Dim index As Integer

            Zed.GraphPane.FindNearestObject(mousePt, Zed.CreateGraphics, NearestObject, index)

            With menuStrip.Items
                .Add(ZoomPrevMenu)
                .Add(ZoomLimitsMenu)
                .Add(ZoomAllMenu)
                .Add(ZoomMenu)
                .Add(New ToolStripSeparator)
                .Add(SendMenu)
                .Add(ExcelMenu)
                .Add(PDFMenu)
                .Add(New ToolStripSeparator)
                .Add(OptionsMenu)
                If TypeOf NearestObject Is ZedGraph.Axis Then
                    SelectedAxis = NearestObject
                    AxesMenu.Text = String.Format("Configure Axis '{0}'...", SelectedAxis.Title.Text)
                    .Add(AxesMenu)
                    If Not TypeOf NearestObject Is ZedGraph.XAxis Then menuStrip.Items.Add(ScaleMenu)
                    If TypeOf NearestObject Is ZedGraph.YAxis Then SelectedAxisIndex = 1 Else SelectedAxisIndex = 2
                ElseIf TypeOf NearestObject Is ZedGraph.LineItem Then
                    SelectedAxis = Nothing
                    With CType(NearestObject, ZedGraph.LineItem)
                        SelectedCurveIndex = Zed.GraphPane.CurveList.IndexOf(NearestObject)
                        HideMenu.Text = String.Format("Hide Series '{0}'", .Label.Text)
                    End With
                    menuStrip.Items.Add(HideMenu)
                ElseIf TypeOf NearestObject Is ZedGraph.ArrowObj Then
                    DrawMenu.Text = "Edit Drawing Object (Arrow)"
                    menuStrip.Items.Add(DrawMenu)
                    DrawRedrawMenu.Image = My.Resources.DrawArrow
                    DrawRedrawMenu.ImageTransparentColor = Color.Fuchsia
                ElseIf TypeOf NearestObject Is ZedGraph.LineObj Then
                    DrawMenu.Text = "Edit Drawing Object (Line)"
                    menuStrip.Items.Add(DrawMenu)
                    DrawRedrawMenu.Image = My.Resources.DrawLine
                    DrawRedrawMenu.ImageTransparentColor = Color.Fuchsia
                ElseIf TypeOf NearestObject Is ZedGraph.BoxObj Then
                    DrawMenu.Text = "Edit Drawing Object (Box)"
                    menuStrip.Items.Add(DrawMenu)
                    DrawRedrawMenu.Image = My.Resources.DrawBox
                    DrawRedrawMenu.ImageTransparentColor = Color.Fuchsia
                ElseIf TypeOf NearestObject Is ZedGraph.EllipseObj Then
                    DrawMenu.Text = "Edit Drawing Object (Ellipse)"
                    menuStrip.Items.Add(DrawMenu)
                    DrawRedrawMenu.Image = My.Resources.DrawEllipse
                    DrawRedrawMenu.ImageTransparentColor = Color.Fuchsia
                ElseIf TypeOf NearestObject Is ZedGraph.TextObj Then
                    DrawMenu.Text = "Edit Drawing Object (Textbox)"
                    menuStrip.Items.Add(DrawMenu)
                    DrawRedrawMenu.Image = My.Resources.DrawText
                    DrawRedrawMenu.ImageTransparentColor = Color.Fuchsia
                Else
                    menuStrip.Items.Add(ShowMenu)
                End If
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub ZedAxes(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            With New frmOptions()
                If SelectedAxis Is Zed.GraphPane.XAxis Then
                    .DefaultAxis = 0
                Else
                    '.DefaultAxis = IIf(SelectedAxis Is Zed.GraphPane.YAxisList, 1, 2)
                    .DefaultAxis = SelectedAxisIndex
                    For i As Integer = 1 To 2
                        For j As Integer = 0 To 4
                            If SelectedAxis Is Choose(i, Zed.GraphPane.YAxisList(j), Zed.GraphPane.Y2AxisList(j)) Then
                                .DefaultIndex = j
                                Exit For
                            End If
                        Next
                    Next
                End If
                .ShowDialog()
            End With
            GraphForm.pgAxes.Refresh()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub ZedExcel(ByVal sender As Object, ByVal e As System.EventArgs)
        SendToExcel()
    End Sub

    Private Sub ZedSend(ByVal sender As Object, ByVal e As System.EventArgs)
        GraphForm.mnuFileImage.PerformClick()
    End Sub

    Private Sub ZedHide(ByVal sender As Object, ByVal e As System.EventArgs)
        Zed.GraphPane.CurveList(SelectedCurveIndex).IsVisible = False
        Zed.GraphPane.CurveList(SelectedCurveIndex).Label.IsVisible = False
        Zed.AxisChange()
        Zed.Refresh()
    End Sub

    Private Sub ZedManage(ByVal sender As Object, ByVal e As System.EventArgs)
        GraphForm.ManageSeries(False)
    End Sub

    Private Sub ZedOptions(ByVal sender As Object, ByVal e As System.EventArgs)
        With New frmOptions
            .TabControl1.SelectedIndex = 1
            .ShowDialog(GraphForm)
        End With
    End Sub

    Private Sub ZedPDF(ByVal sender As Object, ByVal e As System.EventArgs)
        'todo: implement sending zedgraph to pdf (allowing it to append too)
        WarningMsg("This item is planned for a future enhancement.")
    End Sub

    Private Sub ZedScale(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            With SelectedAxis.Scale
                Dim max As Double = CLng(.Max / .MajorStep) * .MajorStep
                Dim s As String = InputBox("Auto-scaling will be turned off and the minimum value will be set to 0.0. Specify the maximum value for this axis:", "Set Axis Maximum Scale", max)
                If Not IsNumeric(s) Then Exit Sub
                Dim _AxisExtra As clsAxis.structAxisExtra = clsAxis.AxisExtra(SelectedAxis.Tag)
                .MinAuto = False
                .Min = 0
                .MaxAuto = False
                .Max = Val(s)
                _AxisExtra.MinLimit = .Min
                _AxisExtra.MaxLimit = .Max
                SelectedAxis.Tag = _AxisExtra
            End With
            Zed.AxisChange()
            Zed.Refresh()
            GraphForm.pgAxes.Refresh()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub ZedShow(ByVal sender As Object, ByVal e As System.EventArgs)
        Try
            For Each crv As ZedGraph.LineItem In Zed.GraphPane.CurveList
                crv.IsVisible = True
                crv.Label.IsVisible = True
            Next
            Zed.AxisChange()
            Zed.Refresh()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Private Sub ZedZoom(ByVal sender As Object, ByVal e As System.EventArgs)
        Select Case CType(sender, ToolStripMenuItem).Text
            Case "Horizontal" : GraphOptions.ZoomOption = enumZoomOptions.Horizontal
            Case "Vertical" : GraphOptions.ZoomOption = enumZoomOptions.Vertical
            Case "Both" : GraphOptions.ZoomOption = enumZoomOptions.Both
            Case "Auto" : GraphOptions.ZoomOption = enumZoomOptions.Auto
        End Select
    End Sub

    Private Sub DrawRedraw(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim NearestObj = NearestObject
        If TypeOf NearestObject Is ZedGraph.ArrowObj Then
            ActiveGraphTab.DrawColor = CType(NearestObject, ZedGraph.ArrowObj).Line.Color
            ActiveGraphTab.DrawWidth = CType(NearestObject, ZedGraph.ArrowObj).Line.Width
            GraphForm.mnuDrawArrow.PerformClick()
        ElseIf TypeOf NearestObject Is ZedGraph.LineObj Then
            ActiveGraphTab.DrawColor = CType(NearestObject, ZedGraph.LineObj).Line.Color
            ActiveGraphTab.DrawWidth = CType(NearestObject, ZedGraph.LineObj).Line.Width
            GraphForm.mnuDrawLine.PerformClick()
        ElseIf TypeOf NearestObject Is ZedGraph.BoxObj Then
            ActiveGraphTab.DrawColor = CType(NearestObject, ZedGraph.BoxObj).Border.Color
            ActiveGraphTab.DrawWidth = CType(NearestObject, ZedGraph.BoxObj).Border.Width
            GraphForm.mnuDrawBox.PerformClick()
        ElseIf TypeOf NearestObject Is ZedGraph.EllipseObj Then
            ActiveGraphTab.DrawColor = CType(NearestObject, ZedGraph.EllipseObj).Border.Color
            ActiveGraphTab.DrawWidth = CType(NearestObject, ZedGraph.EllipseObj).Border.Width
            GraphForm.mnuDrawEllipse.PerformClick()
        ElseIf TypeOf NearestObject Is ZedGraph.TextObj Then
            With ActiveGraphTab()
                .DrawMode = clsGraphTab.enumDrawMode.FirstPoint
                .Zed.Cursor = Cursors.SizeAll
                .Zed.IsEnableZoom = False
                .DrawType = clsGraphTab.enumDrawType.RedrawTextbox
                GraphForm._IsModified = True
            End With
        End If
        Zed.GraphPane.GraphObjList.Remove(NearestObj)
        Zed.Refresh()
    End Sub

    Private Sub DrawColorReset(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim clr As Color = Color.Black
        If TypeOf NearestObject Is ZedGraph.ArrowObj Then
            clr = CType(NearestObject, ZedGraph.ArrowObj).Line.Color
        ElseIf TypeOf NearestObject Is ZedGraph.LineObj Then
            clr = CType(NearestObject, ZedGraph.LineObj).Line.Color
        ElseIf TypeOf NearestObject Is ZedGraph.BoxObj Then
            clr = CType(NearestObject, ZedGraph.BoxObj).Border.Color
        ElseIf TypeOf NearestObject Is ZedGraph.EllipseObj Then
            clr = CType(NearestObject, ZedGraph.EllipseObj).Border.Color
        Else
            Exit Sub
        End If
        With New ColorDialog
            .Color = clr
            If .ShowDialog(GraphForm) = Windows.Forms.DialogResult.OK Then
                If TypeOf NearestObject Is ZedGraph.ArrowObj Then
                    CType(NearestObject, ZedGraph.ArrowObj).Line.Color = .Color
                ElseIf TypeOf NearestObject Is ZedGraph.LineObj Then
                    CType(NearestObject, ZedGraph.LineObj).Line.Color = .Color
                ElseIf TypeOf NearestObject Is ZedGraph.BoxObj Then
                    CType(NearestObject, ZedGraph.BoxObj).Border.Color = .Color
                ElseIf TypeOf NearestObject Is ZedGraph.EllipseObj Then
                    CType(NearestObject, ZedGraph.EllipseObj).Border.Color = .Color
                End If
                .Dispose()
            End If
        End With
        Zed.Refresh()
    End Sub

    Private Sub DrawWidthReset(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim width As Integer = 0
        If TypeOf NearestObject Is ZedGraph.ArrowObj Then
            width = CType(NearestObject, ZedGraph.ArrowObj).Line.Width
        ElseIf TypeOf NearestObject Is ZedGraph.LineObj Then
            width = CType(NearestObject, ZedGraph.LineObj).Line.Width
        ElseIf TypeOf NearestObject Is ZedGraph.BoxObj Then
            width = CType(NearestObject, ZedGraph.BoxObj).Border.Width
        ElseIf TypeOf NearestObject Is ZedGraph.EllipseObj Then
            width = CType(NearestObject, ZedGraph.EllipseObj).Border.Width
        Else
            Exit Sub
        End If
        Dim s As String = InputBox("Enter desired width of lines in points:", "Set Line Width", width)
        If IsNumeric(s) Then
            width = Val(s)
            If TypeOf NearestObject Is ZedGraph.ArrowObj Then
                CType(NearestObject, ZedGraph.ArrowObj).Line.Width = width
                CType(NearestObject, ZedGraph.ArrowObj).Size = width
            ElseIf TypeOf NearestObject Is ZedGraph.LineObj Then
                CType(NearestObject, ZedGraph.LineObj).Line.Width = width
            ElseIf TypeOf NearestObject Is ZedGraph.BoxObj Then
                CType(NearestObject, ZedGraph.BoxObj).Border.Width = width
            ElseIf TypeOf NearestObject Is ZedGraph.EllipseObj Then
                CType(NearestObject, ZedGraph.EllipseObj).Border.Width = width
            End If
        End If
        Zed.Refresh()
    End Sub

    Private Sub DrawDelete(ByVal sender As Object, ByVal e As System.EventArgs)
        Zed.GraphPane.GraphObjList.Remove(NearestObject)
        Zed.Refresh()
    End Sub

    Private Sub DrawDeleteAll(ByVal sender As Object, ByVal e As System.EventArgs)
        GraphForm.mnuDrawDeleteAll.PerformClick()
    End Sub

    Private Sub DrawHideAll(ByVal sender As Object, ByVal e As System.EventArgs)
        GraphForm.mnuDrawHideAll.PerformClick()
    End Sub

    Private Sub DrawShowAll(ByVal sender As Object, ByVal e As System.EventArgs)
        GraphForm.mnuDrawShowAll.PerformClick()
    End Sub

#End Region

    Friend Enum enumProfileXPlot
        RiverMile
        SegmentNum
    End Enum

    ''' <summary>
    ''' Set when user selects which axis to edit--used by AxisTypeConverter
    ''' </summary>
    Friend Shared CurrentAxisType As enumAxisType

    Sub New(ByVal Zed As ZedGraph.ZedGraphControl)
        _Zed = Zed
        AddHandler Zed.GraphPane.AxisChangeEvent, AddressOf Zed_AxisChange
        _GraphOptions = New clsGraphOptions(Zed)
        GraphOptions.Reset()
        _Series = New Generic.List(Of clsSeries)
        AnimationInfo = New clsAnimationInfo
        Zed.GraphPane.Title.IsVisible = False
        Zed.GraphPane.IsAlignGrids = True
        Zed.GraphPane.Border.IsVisible = False
        Zed.MasterPane.Border.IsVisible = False
        Reset()
        'GraphForm.LoadSettings()
    End Sub

    ''' <summary>
    ''' Add new series which will later be configured
    ''' </summary>
    Friend Function AddSeries() As Boolean
        Try
            Dim ser As clsSeries = Nothing
            Select Case _GraphType
                Case enumGraphType.TimeSeries
                    ser = New clsSeriesTimeSeries(Zed)
                Case enumGraphType.Profile
                    ser = New clsSeriesLongProfile(Zed)
                Case enumGraphType.Depth
                    ser = New clsSeriesDepthProfile(Zed)
                Case enumGraphType.Width
                    ser = New clsSeriesWidthProfile(Zed)
                Case enumGraphType.Scatter
                    ser = New clsSeriesScatter(Zed)
                Case enumGraphType.Histogram
                    ser = New clsSeriesHistogram(Zed)
                Case enumGraphType.Probability
                    ser = New clsSeriesProbability(Zed)
                Case enumGraphType.FlowDuration
                    ser = New clsSeriesFlowDuration(Zed)
            End Select
            Zed.GraphPane.CurveList.Insert(0, ser.ZedCurve)
            _Series.Add(ser)
            Return True
        Catch ex As Exception
            ErrorMsg(, ex)
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Add new series containing calculated points
    ''' </summary>
    ''' <param name="zc">Fully populated zedcurve with data points</param>
    ''' <param name="FitStats">String containing fit statistics</param>
    Friend Function AddSeries(ByVal zc As ZedGraph.LineItem, ByVal FitStats As String) As Boolean
        Try
            Dim ser As clsSeries = Nothing
            Select Case _GraphType
                Case enumGraphType.TimeSeries
                    ser = New clsSeriesTimeSeries(Zed)
                Case enumGraphType.Profile
                    ser = New clsSeriesLongProfile(Zed)
                Case enumGraphType.Depth
                    ser = New clsSeriesDepthProfile(Zed)
                Case enumGraphType.Width
                    ser = New clsSeriesWidthProfile(Zed)
                Case enumGraphType.Scatter
                    ser = New clsSeriesScatter(Zed)
                Case enumGraphType.Histogram
                    ser = New clsSeriesHistogram(Zed)
                Case enumGraphType.Probability
                    ser = New clsSeriesProbability(Zed)
                Case enumGraphType.FlowDuration
                    ser = New clsSeriesFlowDuration(Zed)
            End Select
            ser.IsCalc = True
            ser.ZedCurve = zc
            'Zed.GraphPane.CurveList.Add(zc)
            Zed.GraphPane.CurveList.Insert(0, zc)
            ser.StatsText = FitStats
            _Series.Add(ser)
            Return True
        Catch ex As Exception
            ErrorMsg(, ex)
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Add series containing calculated points after specified base series
    ''' </summary>
    ''' <param name="BaseSeries">Series to which the auxiliary series will take many attributes</param>
    ''' <param name="zc">Fully populated zedcurve with data points</param>
    ''' <param name="FitStats">String containing fit statistics</param>
    ''' <param name="InsertBefore">If true, will insert series before baseseries rather than after</param>
    ''' <remarks>Auxiliary series have same color as base series, no symbols, and medium thickness</remarks>
    Friend Function AddSeries(BaseSeries As clsSeries, zc As ZedGraph.LineItem, FitStats As String, Optional InsertBefore As Boolean = False) As Boolean
        Try
            Dim index As Integer = _Series.IndexOf(BaseSeries) + 1
            Dim ser As clsSeries = Nothing
            Select Case _GraphType
                Case enumGraphType.TimeSeries
                    ser = New clsSeriesTimeSeries(Zed)
                Case enumGraphType.Profile
                    ser = New clsSeriesLongProfile(Zed)
                Case enumGraphType.Depth
                    ser = New clsSeriesDepthProfile(Zed)
                Case enumGraphType.Width
                    ser = New clsSeriesWidthProfile(Zed)
                Case enumGraphType.Scatter
                    ser = New clsSeriesScatter(Zed)
                Case enumGraphType.Histogram
                    ser = New clsSeriesHistogram(Zed)
                Case enumGraphType.Probability
                    ser = New clsSeriesProbability(Zed)
                Case enumGraphType.FlowDuration
                    ser = New clsSeriesFlowDuration(Zed)
            End Select
            _Series.Insert(index, ser)

            ser.RemoveZedCurve()
            ser.ZedCurve = zc
            Zed.GraphPane.CurveList.Insert(Zed.GraphPane.CurveList.IndexOf(BaseSeries.ZedCurve) - IIf(InsertBefore And Zed.GraphPane.CurveList.IndexOf(BaseSeries.ZedCurve) <> 0, 1, 0), ser.ZedCurve)

            With BaseSeries
                ser.IsCalc = True
                ser.StatsText = FitStats
                ser.Table = Nothing
                ser.StationID = .StationID
                ser.StationList = .StationID
                ser.PCode = .PCode
                ser.PCodeList = .PCode 'don't allow user to change station or pcode for calculated series
                ser.XAxis = .XAxis
                ser.YAxis = .YAxis
                ser.YAxisIndex = .YAxisIndex
                ser.Label = zc.Label.Text
                'ser.LineColor = .LineColor
                'Tim doesn't want the calculated series to take the same color as the parent series
                ser.LineColor = GraphOptions.DefaultSeriesColor(Array.IndexOf(GraphOptions.DefaultSeriesColor, BaseSeries.LineColor) + 1)
                ser.LineType = clsSeries.enumLineType.Solid
                ser.LineWidth = .LineWidth
                ser.SymbolType = clsSeries.enumSymbolType.None
                Select Case _GraphType
                    Case enumGraphType.Profile
                        CType(ser, clsSeriesLongProfile).ProfXPlot = ActiveGraphTab.ProfileXPlot
                    Case enumGraphType.Scatter
                        With CType(ser, clsSeriesScatter)
                            .StationIDX = CType(BaseSeries, clsSeriesScatter).StationIDX
                            .PCodeX = CType(BaseSeries, clsSeriesScatter).PCodeX
                            .PCodeListX = .PCodeX
                        End With
                    Case enumGraphType.Histogram
                        CType(ser, clsSeriesHistogram).NumIntervals = ActiveGraphTab.AnimationInfo.NumIntervals
                End Select
            End With
            Return True
        Catch ex As Exception
            ErrorMsg(, ex)
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Add auxiliary curve containing calculated points to a given base series (no longer used)
    ''' </summary>
    ''' <param name="BaseSeries">Series to which the auxiliary series will be attached</param>
    ''' <param name="Label">Label to assign the new curve</param>
    ''' <param name="X">Array of x values</param>
    ''' <param name="Y">Array of y values</param>
    ''' <remarks>Auxiliary series have same color as base series, no symbols, and medium thickness</remarks>
    Friend Function AddSeries(ByVal BaseSeries As clsSeries, ByVal Label As String, ByVal X() As Double, ByVal Y() As Double) As Boolean
        Try
            With BaseSeries
                'Dim zc As New ZedGraph.LineItem(Label, X, Y, .LineColor, SymbolType.None, 1)
                '.ZedCurveAux.Add(zc)

                'Zed.GraphPane.CurveList.Add(ser.ZedCurve)
            End With
            Return True
        Catch ex As Exception
            ErrorMsg(, ex)
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Add a new series with the specified station and pcode
    ''' </summary>
    ''' <param name="Table">Table from which the data come</param>
    ''' <param name="StationID">Station ID (or branch name for longitudinal profiles)</param>
    ''' <param name="PCode">Parameter Code</param>
    ''' <param name="DateTime">Date-time value for profile series (if Date.MinValue, will set to first value in data series)</param>
    ''' <param name="TimeWindow">Time window for profile series</param>
    ''' <param name="StationList">Semicolon-separated string of available station ids</param>
    ''' <param name="PCodeList">Semicolon-separated string of available pcodes</param>
    ''' <param name="DateList">Semicolon-separated string of available dates</param>
    ''' <param name="YAxis">Which y-axis to add to (left/right)</param>
    ''' <param name="YAxisIndex">Which y-axis number to add to (ignored if AutoYAxisIndex is true)</param>
    ''' <param name="AutoYAxisIndex">If true, will assign series to existing matching axis or add; otherwise will assign to specified axis index</param>
    Friend Function AddSeries(Table As clsTable, StationID As String, PCode As String, DateTime As Date, TimeWindow As enumTimeWindow, StationList As String, PCodeList As String, DateList As String, YAxis As clsSeries.enumYAxis, YAxisIndex As clsSeries.enumYAxisIndex, AutoYAxisIndex As Boolean, Optional MoreCriteria As clsMoreCriteria = Nothing) As Boolean

        Static AlreadyWarned As Boolean = False
        Dim ser As clsSeries = Nothing
        Try
            Application.UseWaitCursor = True

            Select Case _GraphType
                Case enumGraphType.TimeSeries
                    _Series.Add(New clsSeriesTimeSeries(Zed))
                Case enumGraphType.Profile
                    _Series.Add(New clsSeriesLongProfile(Zed))
                Case enumGraphType.Depth
                    _Series.Add(New clsSeriesDepthProfile(Zed))
                Case enumGraphType.Width
                    _Series.Add(New clsSeriesWidthProfile(Zed))
                Case enumGraphType.Scatter
                    _Series.Add(New clsSeriesScatter(Zed))
                Case enumGraphType.Histogram
                    _Series.Add(New clsSeriesHistogram(Zed))
                Case enumGraphType.Probability
                    _Series.Add(New clsSeriesProbability(Zed))
                Case enumGraphType.FlowDuration
                    _Series.Add(New clsSeriesFlowDuration(Zed))
            End Select

            ser = _Series(_Series.Count - 1)
            With ser
                .Visible = True
                .IsCalc = False
                .Table = Table
                .StationID = StationID
                .PCode = PCode
                .DateTime = DateTime
                .TimeWindow = TimeWindow
                .StationList = StationList
                .PCodeList = PCodeList
                .DateList = DateList
                If GraphType = enumGraphType.Depth Then
                    .YAxis = clsSeries.enumYAxis.Left
                    .XAxis = IIf(YAxis = clsSeries.enumYAxis.Left, clsSeries.enumXAxis.Bottom, clsSeries.enumXAxis.Top)
                Else
                    .XAxis = clsSeries.enumXAxis.Bottom
                    .YAxis = YAxis
                    If AutoYAxisIndex Then
                        SetSeriesAxis(ser, AutoYAxisIndex)
                    Else
                        .YAxisIndex = YAxisIndex
                    End If
                End If

                .MoreCriteria = MoreCriteria

                Select Case _GraphType
                    Case enumGraphType.Profile
                        CType(ser, clsSeriesLongProfile).ProfXPlot = ActiveGraphTab.ProfileXPlot
                    Case enumGraphType.Histogram
                        CType(ser, clsSeriesHistogram).NumIntervals = ActiveGraphTab.AnimationInfo.NumIntervals
                End Select

                If GraphType = enumGraphType.TimeSeries And _Series.Count <= GraphOptions.DefaultSeriesFormats.Count Then
                    'assign default series format if was loaded (and is timeseries)
                    Dim serDefault As clsSeriesTimeSeries = GraphOptions.DefaultSeriesFormats(_Series.Count - 1)
                    .SmoothCurve = serDefault.SmoothCurve
                    .LineColor = serDefault.LineColor
                    .LineType = serDefault.LineType
                    .LineWidth = serDefault.LineWidth
                    .SymbolType = serDefault.SymbolType
                    .SymbolSize = serDefault.SymbolSize
                    .SymbolFill = serDefault.SymbolFill
                    .SymbolBorderColor = serDefault.SymbolBorderColor
                    .SymbolFillColor = serDefault.SymbolFillColor
                Else
                    If _Series.Count = 1 Then
                        .LineColor = GraphOptions.DefaultSeriesColor(0)
                        .SymbolBorderColor = .LineColor
                        .SymbolFillColor = .LineColor
                        .LineWidth = GraphOptions.LineWidth
                        .SmoothCurve = False
                        .SymbolFill = GraphOptions.SymbolFill
                        .SymbolSize = GraphOptions.SymbolSize

                        If GraphOptions.LineType = clsGraphOptions.enumLineType.Auto Then
                            Select Case Table.TableType
                                Case clsTable.enumTableType.BMD, clsTable.enumTableType.BMD2, clsTable.enumTableType.WRDBData
                                    .SymbolType = clsSeries.enumSymbolType.None
                                    .LineType = clsSeries.enumLineType.Solid
                                Case clsTable.enumTableType.Calibration
                                    .SymbolType = clsSeries.enumSymbolType.Circle
                                    .LineType = clsSeries.enumLineType.Solid
                                Case Else
                                    .SymbolType = clsSeries.enumSymbolType.Circle
                                    .LineType = clsSeries.enumLineType.None
                            End Select
                        Else
                            .SymbolType = clsSeries.enumSymbolType.Circle
                            .LineType = GraphOptions.LineType
                        End If
                    Else
                        'determine the color index of the last series and increment from there (otherwise, if remove one series, a new series would have same color as last one)
                        For i As Integer = 0 To GraphOptions.DefaultSeriesColor.Length - 1
                            If GraphOptions.DefaultSeriesColor(i) = _Series(_Series.Count - 2).LineColor Then .LineColor = GraphOptions.DefaultSeriesColor(i + 1) : Exit For
                        Next
                        .SymbolBorderColor = .LineColor
                        .SymbolFillColor = .LineColor
                        Dim serPrev As clsSeries = _Series(_Series.Count - 2)
                        .LineWidth = serPrev.LineWidth
                        .SmoothCurve = serPrev.SmoothCurve
                        .SymbolFill = serPrev.SymbolFill
                        .SymbolSize = serPrev.SymbolSize

                        If GraphOptions.LineType = clsGraphOptions.enumLineType.Auto Then
                            Select Case Table.TableType
                                Case clsTable.enumTableType.BMD, clsTable.enumTableType.BMD2, clsTable.enumTableType.WRDBData
                                    .SymbolType = clsSeries.enumSymbolType.None
                                    .LineType = clsSeries.enumLineType.Solid
                                Case clsTable.enumTableType.Calibration
                                    .SymbolType = clsSeries.enumSymbolType.Circle
                                    .LineType = clsSeries.enumLineType.Solid
                                Case Else
                                    .SymbolType = (serPrev.SymbolType + 1) Mod 10 'there are ten different symbol types
                                    If .SymbolType = clsSeries.enumSymbolType.None Then .SymbolType += 1
                                    .LineType = clsSeries.enumLineType.None
                            End Select
                        Else 'if default is not auto, use that type and always show unique symbols
                            .SymbolType = (serPrev.SymbolType + 1) Mod 10 'there are ten different symbol types
                            If .SymbolType = clsSeries.enumSymbolType.None Then .SymbolType += 1
                            .LineType = GraphOptions.LineType
                        End If
                    End If
                End If

                'override with calibration format settings if applicable 
                If .Table.TableType = clsTable.enumTableType.Calibration Then
                    'use pre-defined formatting stored with calibration dataset
                    'if only one series format, use that
                    For Each fmt As clsSeriesFormat In .Table.Calibration.SeriesFormats
                        If (String.IsNullOrEmpty(fmt.StationFilter) OrElse .Table.Calibration.SeriesFormats.Count <= 1 OrElse .StationID Like fmt.StationFilter) AndAlso
                           (String.IsNullOrEmpty(fmt.ParameterFilter) OrElse .Table.Calibration.SeriesFormats.Count <= 1 OrElse .PCode Like fmt.ParameterFilter) Then
                            .SmoothCurve = False
                            .LineColor = fmt.LineColor
                            .LineType = fmt.LineType
                            .LineWidth = fmt.LineWidth
                            .SymbolType = fmt.SymbolType
                            .SymbolSize = fmt.SymbolSize
                            .SymbolBorderColor = fmt.SymbolBorderColor
                            .SymbolFillColor = fmt.SymbolFillColor
                            .SymbolFill = fmt.SymbolFill
                        End If
                    Next
                End If

                Dim dt As Date = DateTime

                If dt = Date.MinValue Then

                    Select Case .Table.TableType

                        Case clsTable.enumTableType.BMD
                            .Table.dsBMD.Reopen()
                            dt = .Table.dsBMD.Time(0)
                            .Table.dsBMD.Close()

                        Case clsTable.enumTableType.BMD2
                            .Table.dsBMD2.Reopen()
                            dt = .Table.dsBMD2.NthMoment(0)
                            .Table.dsBMD2.Close()

                        Case clsTable.enumTableType.WRDBData
                            If _GraphType = enumGraphType.TimeSeries Then
                                With .Table.dsData
                                    .ActiveStationID = StationID
                                    .Read()
                                    dt = CDate(.Items("Date_Time"))
                                End With
                            End If

                        Case clsTable.enumTableType.Calibration
                            Dim mindate, maxdate As Date
                            If .Table.GetDateRange(mindate, maxdate) Then dt = mindate
                            'If .Table.GetDateList(StationID, PCode).Count > 0 Then
                            '    dt = CDate(.Table.Calibration.tblSimulated.GetDateList(StationID, PCode)(0))
                            'End If

                        Case Else
                            Dim sqlDT As String
                            If .Table.WRDBProject.DB.DatabaseType = clsDB.enumDBType.MySQL Then 'there is a bug in MySQL where aggregate functions return array of bytes
                                sqlDT = "TIMESTAMP(MIN(Date_Time))"
                            Else
                                sqlDT = "MIN(Date_Time)"
                            End If
                            Try
                                Select Case _GraphType
                                    Case enumGraphType.Profile
                                        dt = .Table.WRDBProject.DB.ExecuteScalar("Select {0} FROM {1} WHERE PCode='{2}'", sqlDT, .Table.TableName, PCode)
                                    Case enumGraphType.Width
                                        dt = TestNull(.Table.WRDBProject.DB.ExecuteScalar("Select {0} FROM {1} WHERE Station_ID='{2}' AND PCode='{3}' AND LEW_Pct IS NOT NULL", sqlDT, .Table.TableName, StationID, PCode), "1/1/2000")
                                    Case enumGraphType.Depth
                                        dt = TestNull(.Table.WRDBProject.DB.ExecuteScalar("Select {0} FROM {1} WHERE Station_ID='{2}' AND PCode='{3}' AND Depth_M IS NOT NULL", sqlDT, .Table.TableName, StationID, PCode), "1/1/2000")
                                    Case enumGraphType.Scatter
                                        dt = TestNull(.Table.WRDBProject.DB.ExecuteScalar("Select {0} FROM {1} WHERE Station_ID='{2}' AND PCode='{3}'", sqlDT, .Table.TableName, StationID, PCode), "1/1/2000")
                                End Select
                            Catch ex As Exception
                                Return False
                            End Try

                    End Select
                End If

                Select Case _GraphType
                    'Case enumGraphType.Profile 'must set date-time--start with first one
                    '    With CType(ser, clsSeriesLongProfile)
                    '        .DateTime = dt
                    '        If .Table.TableType = clsTable.enumTableType.BMD Or .Table.TableType = clsTable.enumTableType.BMD2 Then
                    '            'If False And .Table.BMDFieldIndex(clsTable.enumBMDField.RiverMile) = -1 Then
                    '            '    .ProfXPlot = enumProfileXPlot.SegmentNum
                    '            'End If
                    '            .LineType = clsSeries.enumLineType.Solid
                    '            .SymbolType = clsSeries.enumSymbolType.None
                    '            .SymbolFill = False
                    '        Else
                    '            .LineType = clsSeries.enumLineType.None
                    '            '.SymbolType = clsSeries.enumSymbolType.Circle
                    '            .SymbolFill = True
                    '        End If
                    '    End With
                    'Case enumGraphType.Depth
                    '    With CType(ser, clsSeriesDepthProfile)
                    '        .DateTime = dt
                    '        .TimeWindow = enumTimeWindow.None
                    '    End With
                    'Case enumGraphType.Width
                    '    With CType(ser, clsSeriesWidthProfile)
                    '        .DateTime = dt
                    '        .TimeWindow = ActiveGraphTab.AnimationInfo.TimeWindow
                    '    End With
                    Case enumGraphType.Profile, enumGraphType.Width, enumGraphType.Depth
                        .DateTime = dt
                        If .Table.TableType = clsTable.enumTableType.BMD Or .Table.TableType = clsTable.enumTableType.BMD2 Then
                            .LineType = clsSeries.enumLineType.Solid
                            .SymbolType = clsSeries.enumSymbolType.None
                            .SymbolFill = False
                            .TimeWindow = enumTimeWindow.BMD
                        Else
                            .LineType = clsSeries.enumLineType.None
                            .SymbolFill = True
                            .TimeWindow = enumTimeWindow._1_Hour
                        End If
                    Case enumGraphType.Scatter
                        With CType(ser, clsSeriesScatter)
                            .StationIDX = StationID
                            .PCodeX = PCode
                            .PCodeListX = PCodeList
                            '.TimeWindow = ActiveGraphTab.AnimationInfo.TimeWindow
                        End With
                    Case enumGraphType.FlowDuration
                        .LineType = clsSeries.enumLineType.Solid
                        .SymbolType = clsSeries.enumSymbolType.None
                End Select

                'InitializeWDM(.Table)

                .GetData()
                .GetDefaultLabel()
                If .ZedCurve.NPts = 0 Then
                    'remove series without warning--too many prompts!
                    If Not (AlreadyWarned Or ExpertMode) Then
                        If Table.TableType = clsTable.enumTableType.Calibration Then
                            WarningMsg("Unable to add series from calibration dataset because there were no coincident measured and computed data having PCode '{0}' for station '{1}'.\n\nThis message will not be repeated this session.", .PCode, .StationID)
                        Else
                            Select Case GraphType
                                Case enumGraphType.Profile, enumGraphType.Depth, enumGraphType.Width, enumGraphType.Scatter
                                    'don't warn if using time window
                                Case Else
                                    WarningMsg("Unable to add series '{0}' because data having PCode '{1}' does not exist for station '{2}'.\n\nThis message will not be repeated this session.", .Label, .PCode, .StationID)
                            End Select
                        End If
                        AlreadyWarned = True
                    End If
                    Dim AddSeriesAnyway As Boolean = False
                    If ExpertMode Then
                        AddSeriesAnyway = True
                    Else
                        Select Case _GraphType
                            Case enumGraphType.Depth, enumGraphType.Profile, enumGraphType.Width, enumGraphType.Scatter
                                If ExpertMode OrElse WarningMsg("The series you just added ({0}) to this graph has no data points. This may be due to the time window being set too small such that (nearly) coincident observations did not occur. Do you want to add the series anyway so you have the opportunity to change the time window setting for the series?", .Label) = DialogResult.OK Then AddSeriesAnyway = True
                        End Select
                        AlreadyWarned = True
                    End If
                    If Not AddSeriesAnyway Then
                        .RemoveZedCurve()
                        _Series.Remove(ser)
                        Return False
                    End If
                End If
            End With

            Select Case ActiveGraphTab.GraphType
                Case enumGraphType.Probability, enumGraphType.Width, enumGraphType.Depth : ActiveGraphTab.ResetProfileScales()
            End Select

            ResetYAxes()
            Return True

        Catch ex As OutOfMemoryException
            ErrorMsg("WRDB Graph has run out of memory trying to load the BMD file. You can unload all BMD files, select Options | Program Settings | Reduce memory usage by BMD files, and reload them; although performance will be reduced, you will no longer get these error messages.", ex)

        Catch ex As Exception
            ErrorMsg("Unable to add series; data file may be corrupted.", ex)
            If ser IsNot Nothing Then
                With ser
                    .RemoveZedCurve()
                    _Series.Remove(ser)
                End With
            End If
            Return False
        Finally
            Application.UseWaitCursor = False
        End Try
    End Function

    ''' <summary>
    ''' Reacquire the data for all series in graph at user's request (in case source data has been updated)
    ''' </summary>
    Friend Sub Refresh()
        Try
            'For Each tbl As clsTable In OpenTables
            '    If tbl.TableType = clsTable.enumTableType.WRDB5 AndAlso tbl.SqlString <> "" Then
            '        Dim IniFile As New WRDB.Project.clsWRDBIniFile
            '        tbl.SqlString = IniFile.GetKey(WRDB.Project.clsWRDBIniFile.enumSection.Application, WRDB.Project.clsWRDBIniFile.enumKey.AppLastQuerySQL)
            '        tbl.CreateTempData()
            '    End If
            'Next
            For Each ser As clsSeries In Series
                If ser.Table IsNot Nothing AndAlso (ser.Table.TableType = clsTable.enumTableType.BMD Or ser.Table.TableType = clsTable.enumTableType.BMD2) Then ser.Table.KeepFileOpen = False 'to force it to reopen to get new data
                ser.GetData()
                Zed.AxisChange()
                Zed.Refresh()
            Next
            If StatsForm IsNot Nothing Then StatsForm.Refresh()
            If TableForm IsNot Nothing Then TableForm.Refresh()

        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Create a deep copy of the source graph tab
    ''' </summary>
    ''' <param name="SourceGraphTab">Graph tab object from which to make copy</param>
    Friend Shared Function Clone(ByVal SourceGraphTab As clsGraphTab) As clsGraphTab
        Try
            Dim DestZed As New ZedGraph.ZedGraphControl
            DestZed.GraphPane = SourceGraphTab.Zed.GraphPane.Clone
            DestZed.GraphPane.CurveList.Clear() 'don't want curves--will add below
            Dim DestGraphTab As New clsGraphTab(DestZed)
            With DestGraphTab
                With .AnimationInfo
                    .DateTime = SourceGraphTab.AnimationInfo.DateTime
                    .MaxDate = SourceGraphTab.AnimationInfo.MaxDate
                    .MaxNode = SourceGraphTab.AnimationInfo.MaxNode
                    .MinDate = SourceGraphTab.AnimationInfo.MinDate
                    .NodeNum = SourceGraphTab.AnimationInfo.NodeNum
                    .Speed = SourceGraphTab.AnimationInfo.Speed
                    '.TimeStep = SourceGraphTab.AnimationInfo.TimeStep
                    .TimeWindow = SourceGraphTab.AnimationInfo.TimeWindow
                    .ToolbarVisible = SourceGraphTab.AnimationInfo.ToolbarVisible
                End With
                With .GraphOptions
                    .AutoGraphTitle = SourceGraphTab.GraphOptions.AutoGraphTitle
                    .FillColor = SourceGraphTab.GraphOptions.FillColor
                    '.GraphBorder = SourceGraphTab.GraphOptions.GraphBorder
                    .GraphTitle = SourceGraphTab.GraphOptions.GraphTitle
                    .LegendBorder = SourceGraphTab.GraphOptions.LegendBorder
                    .Zed.GraphPane.Legend.FontSpec = SourceGraphTab.Zed.GraphPane.Legend.FontSpec.Clone
                    .LegendFont = SourceGraphTab.GraphOptions.LegendFont
                    .LegendPos = SourceGraphTab.GraphOptions.LegendPos
                    .LegendVisible = SourceGraphTab.GraphOptions.LegendVisible
                    .NotePosition = SourceGraphTab.GraphOptions.NotePosition
                    .NoteText = SourceGraphTab.GraphOptions.NoteText
                    .ScrollBars = SourceGraphTab.GraphOptions.ScrollBars
                    .ShowPoints = SourceGraphTab.GraphOptions.ShowPoints
                    .Zed.GraphPane.Title.FontSpec = SourceGraphTab.Zed.GraphPane.Title.FontSpec.Clone
                    .TitleFont = SourceGraphTab.GraphOptions.TitleFont
                    .ZoomOption = SourceGraphTab.GraphOptions.ZoomOption
                End With
                .GraphType = SourceGraphTab.GraphType
                .ProfileXPlot = SourceGraphTab.ProfileXPlot
                For Each ser As clsSeries In SourceGraphTab.Series
                    If ser.IsCalc Then
                        .AddSeries(ser.ZedCurve, ser.StatsText)
                    Else
                        .AddSeries(ser.Table, ser.StationID, ser.PCode, ser.DateTime, ser.TimeWindow, ser.StationList, ser.PCodeList, ser.DateList, ser.YAxis, ser.YAxisIndex, False)
                    End If
                    With .Series(.Series.Count - 1)
                        .Label = ser.Label
                        .LineColor = ser.LineColor
                        .LineType = ser.LineType
                        .LineWidth = ser.LineWidth
                        .PCode = ser.PCode
                        .PCodeList = ser.PCodeList
                        .SmoothCurve = ser.SmoothCurve
                        .StationID = ser.StationID
                        .StationList = ser.StationList
                        .SymbolFill = ser.SymbolFill
                        .SymbolSize = ser.SymbolSize
                        .SymbolType = ser.SymbolType
                        .Visible = ser.Visible
                    End With
                Next
                .ZoomExtents()
                Dim SourceAxis, DestAxis As ZedGraph.Axis
                For xy As Integer = 1 To 2
                    For i As Integer = 1 To 2
                        For j As Integer = 0 To Choose(xy, 0, 4)
                            With SourceGraphTab.Zed.GraphPane
                                SourceAxis = Choose(xy, Choose(i, .XAxis, .X2Axis), Choose(i, .YAxisList(j), .Y2AxisList(j)))
                            End With
                            With .Zed.GraphPane
                                DestAxis = Choose(xy, Choose(i, .XAxis, .X2Axis), Choose(i, .YAxisList(j), .Y2AxisList(j)))
                            End With
                            With DestAxis
                                .IsVisible = SourceAxis.IsVisible
                                .Title = SourceAxis.Title.Clone
                                .Type = SourceAxis.Type
                                With .Scale
                                    .FontSpec = SourceAxis.Scale.FontSpec.Clone
                                    .MagAuto = SourceAxis.Scale.MagAuto
                                    .MaxAuto = SourceAxis.Scale.MaxAuto
                                    If Not .MaxAuto Then .Max = SourceAxis.Scale.Max
                                    .MinAuto = SourceAxis.Scale.MinAuto
                                    If Not .MinAuto Then .Min = SourceAxis.Scale.Min
                                    .IsReverse = SourceAxis.Scale.IsReverse
                                End With
                                .MajorGrid.IsVisible = SourceAxis.MajorGrid.IsVisible
                                .MinorGrid.IsVisible = SourceAxis.MinorGrid.IsVisible
                                Dim tag As clsAxis.structAxisExtra = Nothing
                                tag.AutoTitle = clsAxis.AxisExtra(SourceAxis.Tag).AutoTitle
                                tag.AutoMaxLog = clsAxis.AxisExtra(SourceAxis.Tag).AutoMaxLog
                                tag.AutoMinLog = clsAxis.AxisExtra(SourceAxis.Tag).AutoMinLog
                                tag.MinLimit = clsAxis.AxisExtra(SourceAxis.Tag).MinLimit
                                tag.MaxLimit = clsAxis.AxisExtra(SourceAxis.Tag).MaxLimit
                                tag.LabelFont = clsAxis.AxisExtra(SourceAxis.Tag).LabelFont
                                tag.TitleFont = clsAxis.AxisExtra(SourceAxis.Tag).TitleFont
                                .Tag = tag
                            End With
                        Next
                    Next
                Next
                .Zed.AxisChange()
                .Zed.Refresh()
            End With
            Return DestGraphTab
        Catch ex As Exception
            ErrorMsg(, ex)
            Return Nothing
        End Try
    End Function

    Private Function GetIndex(ByVal List As Generic.List(Of String), ByVal value As String) As Integer
        Dim i As Integer = Array.BinarySearch(List.ToArray, value)
        If i < 0 Then i = Not i
        Return i
    End Function

    Friend Sub ClearAllSeries()
        _Series.Clear()
        Zed.GraphPane.CurveList.Clear()
    End Sub

    ''' <summary>
    ''' Called in response to pressing of Reset button; resets all graph settings to their default format
    ''' </summary>
    Friend Sub Reset()
        Try
            For i As Integer = 1 To 2
                With New clsAxis(Zed, Choose(i, clsAxis.enumAxis.XAxis, clsAxis.enumAxis.X2Axis), 0, GraphOptions.FontScaleFactor)
                    .Visible = (i = 1)
                    Select Case _GraphType
                        Case enumGraphType.TimeSeries
                            .Title = "Date"
                            .AxisType = ZedGraph.AxisType.Date
                            .Reverse = False
                        Case enumGraphType.Profile
                            If .AutoTitle Then .Title = IIf(_ProfileXPlot = enumProfileXPlot.RiverMile, "River Mile", "Segment Number")
                            .AxisType = ZedGraph.AxisType.Linear
                            .Reverse = _ProfileXPlot = enumProfileXPlot.RiverMile
                        Case enumGraphType.Depth, enumGraphType.Scatter, enumGraphType.Histogram
                            .Title = "Concentration"
                            .AxisType = ZedGraph.AxisType.Linear
                            .Reverse = False
                        Case enumGraphType.Width
                            .Title = "Width"
                            .AxisType = ZedGraph.AxisType.Linear
                            .Reverse = False
                        Case enumGraphType.Probability
                            .Title = "Probability"
                            .AxisType = ZedGraph.AxisType.Probability
                            .Reverse = False
                        Case enumGraphType.FlowDuration
                            .Title = "Flow Duration Interval (%)"
                            .AxisType = ZedGraph.AxisType.Linear
                            .Reverse = False
                            .Min = 0
                            .Max = 100
                    End Select

                    Dim axis As New clsAxis(Zed, Choose(i, clsAxis.enumAxis.XAxis, clsAxis.enumAxis.X2Axis), 0, GraphOptions.FontScaleFactor)
                    axis.TitleFont = New Font("Tahoma", 10, FontStyle.Bold)
                    axis.LabelFont = New Font("Tahoma", 8)
                End With

                'With CType(Choose(i, Zed.GraphPane.XAxis, Zed.GraphPane.X2Axis), ZedGraph.Axis)
                '    .IsVisible = (i = 1)
                '    Select Case _GraphType
                '        Case enumGraphType.TimeSeries
                '            .Title.Text = "Date"
                '            .Type = ZedGraph.AxisType.Date
                '            .Scale.Format = MyDateFormat()
                '            .Scale.IsReverse = False
                '        Case enumGraphType.Profile
                '            If clsAxis.AxisExtra(.Tag).AutoTitle Then .Title.Text = IIf(_ProfileXPlot = enumProfileXPlot.RiverMile, "River Mile", "Segment Number")
                '            .Type = ZedGraph.AxisType.Linear
                '            .Scale.Format = ""
                '            .Scale.FormatAuto = True
                '            .Scale.IsReverse = _ProfileXPlot = enumProfileXPlot.RiverMile
                '        Case enumGraphType.Depth, enumGraphType.Scatter, enumGraphType.Histogram
                '            .Title.Text = "Concentration"
                '            .Type = ZedGraph.AxisType.Linear
                '            .Scale.Format = ""
                '            .Scale.FormatAuto = True
                '            .Scale.IsReverse = False
                '        Case enumGraphType.Width
                '            .Title.Text = "Width"
                '            .Type = ZedGraph.AxisType.Linear
                '            .Scale.Format = ""
                '            .Scale.FormatAuto = True
                '            .Scale.IsReverse = False
                '        Case enumGraphType.Probability
                '            .Title.Text = "Probability"
                '            .Type = ZedGraph.AxisType.Probability
                '            .Scale.Format = ""
                '            .Scale.FormatAuto = True
                '            .Scale.IsReverse = False
                '        Case enumGraphType.FlowDuration
                '            .Title.Text = "Flow Duration Interval (%)"
                '            .Type = ZedGraph.AxisType.Linear
                '            .Scale.Format = ""
                '            .Scale.FormatAuto = True
                '            .Scale.IsReverse = False
                '            .Scale.Min = 0
                '            .Scale.Max = 100
                '    End Select

                '    Dim axis As New clsAxis(Zed, Choose(i, clsAxis.enumAxis.XAxis, clsAxis.enumAxis.X2Axis), 0, GraphOptions.FontScaleFactor)
                '    axis.TitleFont = New Font("Tahoma", 10, FontStyle.Bold)
                '    axis.LabelFont = New Font("Tahoma", 8)
                'End With
            Next

            GraphOptions.UseFontScaleFactor = True 'will force standard fonts on axes

            Zed.GraphPane.XAxis.MajorGrid.IsVisible = True
            Zed.GraphPane.X2Axis.MajorGrid.IsVisible = True
            Zed.GraphPane.YAxis.MajorGrid.IsVisible = False
            Zed.GraphPane.Y2Axis.MajorGrid.IsVisible = False
            For i As Integer = 0 To 4
                With New clsAxis(Zed, clsAxis.enumAxis.YAxis, i, GraphOptions.FontScaleFactor)
                    .Visible = i = 0
                    .AxisType = ZedGraph.AxisType.Linear
                    Select Case _GraphType
                        Case enumGraphType.TimeSeries, enumGraphType.Profile, enumGraphType.Width, enumGraphType.Scatter, enumGraphType.Probability
                            '.Title = "Concentration"
                        Case enumGraphType.Depth
                            .Title = "Depth"
                        Case enumGraphType.Histogram
                            .Title = "Probability"
                        Case enumGraphType.FlowDuration
                            .Title = "Load"
                            .AxisType = AxisType.Log
                    End Select
                End With
                With New clsAxis(Zed, clsAxis.enumAxis.Y2Axis, i, GraphOptions.FontScaleFactor)
                    .Visible = False
                End With
            Next

            'Zed.GraphPane.XAxis.MajorGrid.IsVisible = True
            'Zed.GraphPane.X2Axis.MajorGrid.IsVisible = True
            'Zed.GraphPane.YAxis.MajorGrid.IsVisible = False
            'Zed.GraphPane.Y2Axis.MajorGrid.IsVisible = False
            'With Zed.GraphPane.YAxisList
            '    For i As Integer = 0 To 4
            '        If i > .Count - 1 Then .Add("")
            '        .Item(i).IsVisible = i = 0
            '        .Item(i).Type = ZedGraph.AxisType.Linear
            '        Select Case _GraphType
            '            Case enumGraphType.TimeSeries, enumGraphType.Profile, enumGraphType.Width, enumGraphType.Scatter, enumGraphType.Probability
            '                .Item(i).Title.Text = "Concentration"
            '            Case enumGraphType.Depth
            '                .Item(i).Title.Text = "Depth"
            '            Case enumGraphType.Histogram
            '                .Item(i).Title.Text = "Probability"
            '            Case enumGraphType.FlowDuration
            '                .Item(i).Title.Text = "Load"
            '                .Item(i).Type = AxisType.Log
            '        End Select
            '    Next
            'End With
            'With Zed.GraphPane.Y2AxisList
            '    For i As Integer = 0 To 4
            '        If i > .Count - 1 Then .Add("")
            '        .Item(i).IsVisible = False
            '    Next
            'End With

            For i As Integer = 1 To 2
                For j As Integer = 0 To 4
                    Dim axis As New clsAxis(Zed, Choose(i, clsAxis.enumAxis.YAxis, clsAxis.enumAxis.Y2Axis), j, GraphOptions.FontScaleFactor)
                    axis.TitleFont = New Font("Tahoma", 10, FontStyle.Bold)
                    axis.LabelFont = New Font("Tahoma", 8)
                Next
            Next
            GraphOptions.Reset()
            With New clsAxis(Zed, clsAxis.enumAxis.XAxis, 0, GraphOptions.FontScaleFactor)
                .GridLines = True
            End With
            With New clsAxis(Zed, clsAxis.enumAxis.YAxis, 0, GraphOptions.FontScaleFactor)
                .GridLines = True
            End With
            Zed.GraphPane.IsAlignGrids = True

            If _Series.Count > 0 Then ResetYAxes()
            Zed.GraphPane.AxisChange()
            'ZoomExtents()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Reset axis scales to be appropriate for all times (for profiles only); call when animation begun or animation toolbar becomes visible
    ''' </summary>
    Friend Sub ResetProfileScales()
        Try
            With ActiveGraphTab()
                'define local axis limits for each y axis
                Dim axislimits(0 To 1, 0 To 4, 0 To 1) As Single 'indices are left/right; axisnum; min/max
                Dim xmin As Single = Single.MaxValue, xmax As Single = Single.MinValue

                For i As Integer = 0 To 1
                    For j As Integer = 0 To 4
                        axislimits(i, j, 0) = Single.MaxValue
                        axislimits(i, j, 1) = Single.MinValue
                    Next
                Next
                'for each bmd series, assign limits to axis variable
                For Each ser As clsSeries In .Series
                    With ser
                        If Not .IsCalc Then
                            Dim ymin As Single = Single.MaxValue, ymax As Single = Single.MinValue
                            If .Table.TableType = clsTable.enumTableType.BMD2 Then
                                .Table.dsBMD2.Reopen()
                            End If
                            For Each kv As KeyValuePair(Of String, clsTable.structStationSupport) In .Table.StationSupport
                                If .StationID = "All Branches" OrElse (.StationID = kv.Value.BranchID AndAlso Not Double.IsNaN(kv.Value.RiverMile)) Then
                                    xmin = Math.Min(xmin, kv.Value.RiverMile)
                                    xmax = Math.Max(xmax, kv.Value.RiverMile)
                                    Select Case .Table.TableType
                                        Case clsTable.enumTableType.BMD
                                            With .Table.dsBMD
                                                ymin = Math.Min(ymin, .VarSegMin(ser.PCode, kv.Value.StationID))
                                                ymax = Math.Max(ymax, .VarSegMax(ser.PCode, kv.Value.StationID))
                                            End With
                                        Case clsTable.enumTableType.BMD2
                                            With .Table.dsBMD2
                                                Dim mn, mx As Single
                                                Dim n As Integer = .NumSegments
                                                Dim s As String = .SegmentName(0)
                                                .MinMaxForSegVar(.SegmentIndex(kv.Value.StationID), .VariableIndex(ser.PCode), mn, mx)
                                                ymin = Math.Min(ymin, mn)
                                                ymax = Math.Max(ymax, mx)
                                            End With
                                        Case Else
                                            Dim dt As DataTable = .Table.GetResults(kv.Value.StationID, .PCode)
                                            If dt.Rows.Count > 0 Then
                                                ymin = Math.Min(ymin, dt.Compute("Min(Result)", ""))
                                                ymax = Math.Max(ymax, dt.Compute("Max(Result)", ""))
                                            End If
                                    End Select
                                End If
                            Next
                            If .Table.TableType = clsTable.enumTableType.BMD2 Then
                                .Table.dsBMD2.Close()
                            End If
                            axislimits(.YAxis, .YAxisIndex, 0) = Math.Min(axislimits(.YAxis, .YAxisIndex, 0), ymin)
                            axislimits(.YAxis, .YAxisIndex, 1) = Math.Max(axislimits(.YAxis, .YAxisIndex, 1), ymax)
                        End If
                    End With
                Next

                'if axis variable is modified, reset the limits on the zed axes

                For i As Integer = 0 To 1
                    For j As Integer = 0 To IIf(.GraphType = enumGraphType.Depth, 0, 4)
                        If axislimits(i, j, 0) <> Single.MaxValue Then
                            'axis is being used; add a hidden curve containing two points (min & max) so auto-scale will work
                            For Each crv As ZedGraph.LineItem In .Zed.GraphPane.CurveList
                                If crv.Label.Text = "HIDDEN" AndAlso Choose(i + 1, Not crv.IsY2Axis, crv.IsY2Axis) AndAlso crv.YAxisIndex = j Then
                                    .Zed.GraphPane.CurveList.Remove(crv)
                                    Exit For
                                End If
                            Next
                            Dim newcrv As New ZedGraph.LineItem("HIDDEN")
                            With newcrv
                                If ActiveGraphTab.GraphType = enumGraphType.Depth Then
                                    .IsX2Axis = (i = 1)
                                    .AddPoint(axislimits(i, j, 0), xmin)
                                    .AddPoint(axislimits(i, j, 1), xmax)
                                Else
                                    .IsY2Axis = (i = 1)
                                    .YAxisIndex = j
                                    .AddPoint(xmin, axislimits(i, j, 0))
                                    .AddPoint(xmax, axislimits(i, j, 1) * 1.1)
                                End If
                                .IsVisible = True 'if false, is not used when scaling axes
                                .Line.IsVisible = False
                                .Symbol.IsVisible = False
                                .Label.IsVisible = False
                            End With
                            .Zed.GraphPane.CurveList.Add(newcrv)
                        End If
                    Next
                Next
                .Zed.AxisChange()
                .Zed.Refresh()
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Reset default axis titles based on the data assigned to each axis
    ''' </summary>
    ''' <remarks></remarks>
    Friend Sub ResetYAxes()
        Try
            With Zed.GraphPane
                For xy As Integer = 1 To 2 'primary and secondary (e.g., left/right)
                    With Choose(xy, .XAxis, .X2Axis)
                        .IsVisible = False
                        .Title.Text = ""
                    End With
                    For i As Integer = 0 To 4
                        With CType(Choose(xy, .YAxisList(i), .Y2AxisList(i)), ZedGraph.Axis)
                            .IsVisible = False
                            If clsAxis.AxisExtra(.Tag).AutoTitle Then .Title.Text = ""
                        End With
                    Next
                Next

                For Each ser As clsSeries In _Series

                    Dim YTitle As String = "", XTitle As String = ""
                    Dim PCodeY As String = "", PCodeX As String = ""
                    Select Case _GraphType
                        Case enumGraphType.TimeSeries, enumGraphType.Profile, enumGraphType.Width, enumGraphType.Probability, enumGraphType.FlowDuration
                            PCodeY = ser.PCode
                        Case enumGraphType.Depth, enumGraphType.Histogram
                            PCodeX = ser.PCode
                        Case enumGraphType.Scatter
                            Dim serScatter As clsSeriesScatter = ser
                            PCodeY = serScatter.PCodeY
                            PCodeX = serScatter.PCodeX
                            If serScatter.StationIDX <> serScatter.StationIDY Then
                                PCodeX &= " at " & serScatter.StationIDX
                                PCodeY &= " at " & serScatter.StationIDY
                            End If
                            If Not ser.IsCalc AndAlso ser.Table.TableType = clsTable.enumTableType.Calibration Then
                                PCodeY = ser.Table.Calibration.LegendSuffixSimulated & " " & PCodeY
                                PCodeX = ser.Table.Calibration.LegendSuffixMeasured & " " & PCodeX
                            End If
                    End Select

                    Select Case _GraphType
                        Case enumGraphType.TimeSeries, enumGraphType.Profile, enumGraphType.Probability, enumGraphType.Width, enumGraphType.Scatter, enumGraphType.FlowDuration
                            If Not ser.IsCalc AndAlso ser.Table IsNot Nothing AndAlso
                               PCodeY IsNot Nothing AndAlso
                               ser.Table.PCodeSupport IsNot Nothing AndAlso ser.Table.PCodeSupport.ContainsKey(PCodeY) Then
                                With ser.Table.PCodeSupport(PCodeY)
                                    YTitle = String.Format("{0} {1} {2}", PCodeY, IIf(.Name.Trim = "", "", ": " & .Name.Trim), IIf(.Units.Trim = "", "", "(" & .Units.Trim & ")"))
                                End With
                            Else
                                YTitle = PCodeY
                            End If
                        Case enumGraphType.Depth : YTitle = "Depth"
                        Case enumGraphType.Histogram : YTitle = "Probability"
                    End Select

                    Select Case _GraphType
                        Case enumGraphType.TimeSeries : XTitle = "Date"
                        Case enumGraphType.Profile : XTitle = IIf(_ProfileXPlot = enumProfileXPlot.RiverMile, "River Mile", "Segment Number")
                        Case enumGraphType.Depth, enumGraphType.Scatter, enumGraphType.Histogram
                            If Not ser.IsCalc AndAlso ser.Table.PCodeSupport.ContainsKey(PCodeX) Then
                                With ser.Table.PCodeSupport(PCodeX)
                                    XTitle = String.Format("{0}: {1} {2}", PCodeX, .Name.Trim, IIf(.Units.Trim = "", "", "(" & .Units.Trim & ")"))
                                End With
                            Else
                                XTitle = PCodeX
                            End If
                        Case enumGraphType.Width : XTitle = "Width"
                        Case enumGraphType.Probability : XTitle = "Probability"
                        Case enumGraphType.FlowDuration : XTitle = "Flow Duration Interval (%)"
                        Case Else
                            XTitle = ""
                    End Select

                    With CType(Choose(ser.XAxis + 1, .XAxis, .X2Axis), ZedGraph.Axis)
                        .IsVisible = True
                        If Not String.IsNullOrEmpty(XTitle) AndAlso Not .Title.Text.Contains(XTitle) Then .Title.Text &= IIf(.Title.Text = "", "", "; ") & XTitle
                    End With
                    With CType(Choose(ser.YAxis + 1, .YAxisList(ser.YAxisIndex), .Y2AxisList(ser.YAxisIndex)), ZedGraph.Axis)
                        If clsAxis.AxisExtra(.Tag).AutoTitle Then
                            If Not String.IsNullOrEmpty(YTitle) AndAlso Not .Title.Text.Contains(YTitle) Then .Title.Text &= IIf(.Title.Text = "", "", "; ") & YTitle 'can't use property below because this is called by other property
                        End If
                    End With

                    With New clsAxis(Zed, Choose(ser.YAxis + 1, clsAxis.enumAxis.YAxis, clsAxis.enumAxis.Y2Axis), ser.YAxisIndex, GraphOptions.FontScaleFactor)
                        .Visible = True
                        If Not ((ser.YAxis = clsSeries.enumYAxis.Left) And ser.YAxisIndex = 0) Then .GridLines = False
                        If _GraphType = enumGraphType.Depth Then .Reverse = True

                        'don't want to show tick marks on right axes--sometimes they don't coincide with minor ticks on left (4 vs 5)
                        'would be better to only turn off if not 5, but that would require AxisChange call each time which would be slow
                        'Instead, always turn off minor ticks for right axes.

                        .ZedAxis.MinorTic.IsAllTics = ser.YAxis = clsSeries.enumYAxis.Left

                    End With
                Next

                'reset autotitle for invisible axes
                For xy As Integer = 1 To 2 'primary and secondary (e.g., left/right)
                    With New clsAxis(Zed, Choose(xy, clsAxis.enumAxis.XAxis, clsAxis.enumAxis.X2Axis), 0, GraphOptions.FontScaleFactor)
                        If Not .Visible Then .AutoTitle = True
                    End With
                    For i As Integer = 0 To 4
                        With New clsAxis(Zed, Choose(xy, clsAxis.enumAxis.YAxis, clsAxis.enumAxis.Y2Axis), i, GraphOptions.FontScaleFactor)
                            If Not .Visible Then .AutoTitle = True
                        End With
                    Next
                Next

            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Friend Sub SendToExcel()
        Try
            Dim xl As New WRDB.MSExcel.clsExcel
            Application.UseWaitCursor = True
            Application.DoEvents()
            xl.ExportZedChart(Zed)
            Application.UseWaitCursor = False
        Catch ex As Exception
            ErrorMsg("Unable to connect to Excel libraries on your computer; this feature will only work if you have a compatible version of Excel already installed on your computer.", ex)
        End Try
    End Sub

    'Private Sub SendToPDF(Optional ByVal Preview As Boolean = False, Optional ByVal DefaultFileName As String = "")

    '    ' create new print dialog and set options 
    '    Dim dlg As New SaveFileDialog
    '    With dlg
    '        .AddExtension = True
    '        .DefaultExt = "PDF"
    '        .Filter = "PDF File (*.pdf)|*.pdf"
    '        .OverwritePrompt = False
    '        .SupportMultiDottedExtensions = False
    '        .Title = "Save to PDF"
    '        .FileName = DefaultFileName
    '        If .ShowDialog = DialogResult.OK Then
    '            'convert margins to points
    '            With m_PrintMargins
    '                .Left *= 0.72
    '                .Right *= 0.72
    '                .Top *= 0.72
    '                .Bottom *= 0.72
    '            End With

    '            Dim Append As Boolean = False

    '            If My.Computer.FileSystem.FileExists(.FileName) Then
    '                Select Case MessageBox.Show(String.Format("The file '{0}' already exists. Do you want to overwrite it?\n\nSelect 'Yes' to overwrite, 'No' to append to the existing file.".Replace("\n", vbCr), .FileName), "Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)
    '                    Case DialogResult.Yes : My.Computer.FileSystem.DeleteFile(.FileName) : Append = False
    '                    Case DialogResult.No : Append = True
    '                    Case DialogResult.Cancel : Exit Sub
    '                End Select
    '            End If
    '            Dim pdf As PdfSharp.Pdf.PdfDocument
    '            Dim tempfile As String = My.Computer.FileSystem.GetTempFileName
    '            If Append Then
    '                pdf = PdfSharp.Pdf.IO.PdfReader.Open(.FileName, PdfSharp.Pdf.IO.PdfDocumentOpenMode.Modify)
    '            Else
    '                pdf = New PdfSharp.Pdf.PdfDocument(.FileName)
    '            End If
    '            Dim pdfpage As PdfSharp.Pdf.PdfPage
    '            Dim HasMorePages As Boolean = True
    '            sendToPDF = True
    '            Dim gfx As PdfSharp.Drawing.XGraphics
    '            Do While HasMorePages
    '                pdfpage = pdf.AddPage
    '                SetupPDF(pdf, pdfpage)
    '                gfx = PdfSharp.Drawing.XGraphics.FromPdfPage(pdfpage)
    '                PrintPage(gfx, HasMorePages)
    '            Loop
    '            Try
    '                If Append Then
    '                    pdf.Save(.FileName.Replace(".pdf", "new.pdf"))
    '                    pdf.Close()
    '                Else
    '                    pdf.Close()
    '                    'pdf.Save(.FileName)
    '                End If
    '            Catch ex As Exception
    '                MessageBox.Show("Unable to save PDF file; it is likely already open by another user.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Error)
    '                .Dispose()
    '                Exit Sub
    '            Finally
    '                pdf.Dispose()
    '                pdf = Nothing
    '            End Try
    '            If Preview Then Process.Start(.FileName)
    '        End If
    '        .Dispose()
    '    End With
    'End Sub

    '''' <summary> 
    '''' Set up the print job. Save information from print dialog 
    '''' and print document for easy access. Also sets up the rows 
    '''' and columns that will be printed. 
    '''' </summary> 
    'Private Sub SetupPDF(ByVal pdf As PdfSharp.Pdf.PdfDocument, ByVal pdfPage As PdfSharp.Pdf.PdfPage)

    '    If m_ForceLandscape Then
    '        pdfPage.Orientation = PdfSharp.PageOrientation.Landscape
    '        pdfPage.Rotate = 90
    '    End If
    '    pdfPage.Size = PdfSharp.PageSize.Letter

    '    If pdfPage.Orientation = PdfSharp.PageOrientation.Landscape Then
    '        pageWidth = pdfPage.Height.Point
    '        pageHeight = pdfPage.Width.Point
    '        printWidth = pageWidth - m_PrintMargins.Left - m_PrintMargins.Right
    '    Else
    '        pageWidth = pdfPage.Width.Point
    '        pageHeight = pdfPage.Height.Point
    '        printWidth = pageWidth - m_PrintMargins.Left - m_PrintMargins.Right
    '    End If

    '    ' save print range 
    '    printRange = Printing.PrintRange.AllPages

    '    ' set extremes so that we'll print all pages 
    '    fromPage = 0
    '    toPage = 2147483647

    '    '----------------------------------------------------------------- 
    '    ' set up the rows and columns to print 
    '    '----------------------------------------------------------------- 

    '    ' rows to print (handles "selection" and "current page" options 
    '    If printRange.Selection = printRange Then
    '        ' if DGV has rows selected, it's easy, selected rows and all visible columns 
    '        If 0 <> dgv.SelectedRows.Count Then
    '            RowsToPrint = dgv.SelectedRows
    '            ColsToPrint = New List(Of Object)(dgv.Columns.Count)
    '            For Each col As DataGridViewColumn In dgv.Columns
    '                If col.Visible Then
    '                    ColsToPrint.Add(col)
    '                End If
    '            Next
    '        ElseIf 0 <> dgv.SelectedColumns.Count Then
    '            ' if selected columns, then all rows, and selected columns 
    '            RowsToPrint = dgv.Rows
    '            ColsToPrint = dgv.SelectedColumns
    '        Else
    '            ' we just have a bunch of selected cells so we have to do some work 
    '            ' set up sorted lists. the selectedcells method does not guarantee 
    '            ' that the cells will always be in left-right top-bottom order. 
    '            Dim temprowstoprint As New SortedList(dgv.SelectedCells.Count)
    '            Dim tempcolstoprint As New SortedList(dgv.SelectedCells.Count)

    '            ' for each selected cell, add unique rows and columns 
    '            Dim colindex As Integer, rowindex As Integer
    '            For Each cell As DataGridViewCell In dgv.SelectedCells
    '                colindex = cell.ColumnIndex
    '                rowindex = cell.RowIndex

    '                If Not temprowstoprint.Contains(rowindex) Then
    '                    temprowstoprint.Add(rowindex, dgv.Rows(rowindex))
    '                End If

    '                If Not tempcolstoprint.Contains(colindex) Then
    '                    tempcolstoprint.Add(colindex, dgv.Columns(colindex))
    '                End If
    '            Next

    '            ' Move the now-sorted columns and rows to our list of what to print 
    '            RowsToPrint = New List(Of Object)(temprowstoprint.Count)
    '            For Each item As Object In temprowstoprint.Values
    '                RowsToPrint.Add(item)
    '            Next
    '            ColsToPrint = New List(Of Object)(tempcolstoprint.Count)
    '            For Each item As Object In tempcolstoprint.Values
    '                ColsToPrint.Add(item)
    '            Next
    '        End If
    '    ElseIf printRange.CurrentPage = printRange Then
    '        ' if current page was selected, print visible columns for the 
    '        ' displayed rows 
    '        ' create lists 
    '        RowsToPrint = New List(Of Object)(dgv.DisplayedRowCount(True))
    '        ColsToPrint = New List(Of Object)(dgv.Columns.Count)
    '        For i As Integer = dgv.FirstDisplayedScrollingRowIndex To dgv.FirstDisplayedScrollingRowIndex + dgv.DisplayedRowCount(True) - 1

    '            ' select all visible rows on displayed page 
    '            Dim row As DataGridViewRow = dgv.Rows(i)
    '            If row.Visible Then
    '                RowsToPrint.Add(row)
    '            End If
    '        Next

    '        ' select all visible columns 
    '        ColsToPrint = New List(Of Object)(dgv.Columns.Count)
    '        For Each col As DataGridViewColumn In dgv.Columns
    '            If col.Visible Then
    '                ColsToPrint.Add(col)
    '            End If
    '        Next
    '    Else
    '        ' this is the default for print all - everything marked visible will be printed 
    '        ' select all visible rows and all visible columns 
    '        RowsToPrint = New List(Of Object)(dgv.Rows.Count)
    '        For Each row As DataGridViewRow In dgv.Rows
    '            If row.Visible Then
    '                RowsToPrint.Add(row)
    '            End If
    '        Next

    '        ColsToPrint = New List(Of Object)(dgv.Columns.Count)
    '        For Each col As DataGridViewColumn In dgv.Columns
    '            If col.Visible Then
    '                ColsToPrint.Add(col)
    '            End If
    '        Next
    '    End If
    'End Sub

    ''' <summary>
    ''' Set reasonable graph title for currently active series/timestep (only if AutoGraphTitle is true)
    ''' Will take title from first visible series
    ''' </summary>
    Friend Sub SetGraphTitle()
        Try
            With Me
                If .Zed.GraphPane Is Nothing Then Exit Sub
                If .GraphOptions.AutoGraphTitle Then
                    .Zed.GraphPane.Title.Text = ""
                    Select Case .GraphType
                        Case enumGraphType.TimeSeries, enumGraphType.Histogram, enumGraphType.Probability, enumGraphType.FlowDuration
                            For Each ser As clsSeries In .Series
                                If ser.Visible Then
                                    .Zed.GraphPane.Title.Text = String.Format("Station ID: {0}", ser.StationID)
                                    Exit For
                                End If
                            Next
                        Case enumGraphType.Scatter
                            For Each ser As clsSeriesScatter In .Series
                                If ser.Visible Then
                                    If ser.StationIDX = ser.StationIDY Then
                                        .Zed.GraphPane.Title.Text = String.Format("Station ID: {0}", ser.StationIDX)
                                    Else
                                        .Zed.GraphPane.Title.Text = String.Format("Station IDs: {0} and {1}", ser.StationIDX, ser.StationIDY)
                                    End If
                                    Exit For
                                End If
                            Next
                        Case Else
                            For Each ser As clsSeries In .Series
                                If ser.Visible Then
                                    .Zed.GraphPane.Title.Text = String.Format("Date-Time: {0}", ser.DateTime)
                                    Exit For
                                End If
                            Next
                    End Select
                    .Zed.GraphPane.Title.IsVisible = True
                    '.Zed.Refresh()
                End If
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Change draw order of specified series
    ''' </summary>
    ''' <param name="ser">Series to change</param>
    ''' <param name="Index">New position in draw order</param>
    Friend Sub SetSeriesOrder(ByVal ser As clsSeries, ByVal Index As Integer)
        Try
            Dim gt As clsGraphTab = ActiveGraphTab()
            With gt
                .Series.Remove(ser)
                Index = Math.Max(Math.Min(Index, .Series.Count), 0) 'don't let it be out of bounds
                .Series.Insert(Index, ser)
                .Zed.GraphPane.CurveList.Clear()
                For i As Integer = .Series.Count - 1 To 0 Step -1
                    .Series(i).AddZedCurve()
                Next
                GraphForm._IsModified = True
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Find the best available graph y axis for the series passed
    ''' </summary>
    ''' <param name="ser">Graph series</param>
    ''' <param name="CreateAxis">If true, will create new axis if not already found; otherwise uses last visible axis</param>
    Friend Sub SetSeriesAxis(ByVal ser As clsSeries, ByVal CreateAxis As Boolean)
        Try
            Dim found As Boolean = False
            If CreateAxis Then
                'see if that PCode is already assigned to a Y axis; if so, use it (even if it belongs to an axis other than was requested)
                For j As Integer = 0 To 4
                    With CType(Choose(ser.YAxis + 1, Zed.GraphPane.YAxisList(j), Zed.GraphPane.Y2AxisList(j)), ZedGraph.Axis)
                        If (.Title.Text.Contains(ser.PCode & ":") Or .Title.Text.Contains(ser.PCode & " ") Or .Title.Text = ser.PCode) And .IsVisible Then
                            found = True
                            ser.YAxis = ser.YAxis
                            ser.YAxisIndex = j
                        End If
                    End With
                Next
                If Not found Then
                    'assign the next unused yaxis index on the specified axis but not more than 4
                    Dim maxindex As Integer = -1
                    For i As Integer = 0 To _Series.Count - 2
                        If _Series(i).YAxis = ser.YAxis Then maxindex = Math.Max(maxindex, _Series(i).YAxisIndex)
                    Next
                    ser.YAxisIndex = Math.Min(4, maxindex + 1)
                End If
            Else
                For j As Integer = 4 To 0 Step -1
                    With CType(Choose(ser.YAxis + 1, Zed.GraphPane.YAxisList(j), Zed.GraphPane.Y2AxisList(j)), ZedGraph.Axis)
                        If .IsVisible Then
                            ser.YAxisIndex = j
                            found = True
                            Exit For
                        End If
                    End With
                Next
                If Not found Then 'no axes were visible; assign to first one
                    With CType(Choose(ser.YAxis + 1, Zed.GraphPane.YAxisList(0), Zed.GraphPane.Y2AxisList(0)), ZedGraph.Axis)
                        .IsVisible = True
                        ser.YAxisIndex = 0
                    End With
                End If
            End If
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Set the current date-time for all series (and optionally, time window)
    ''' Used when animating profile plots
    ''' </summary>
    Friend Sub SetSeriesDateTime(ByVal DateTime As Date, Optional ByVal TimeWindow As enumTimeWindow = -1)
        Try
            For Each ser As clsSeries In _Series
                ser.DateTime = DateTime
                If TimeWindow <> -1 Then ser.TimeWindow = TimeWindow
                If Not ser.IsCalc Then
                    ser.GetData()
                    'since datetime has changed, reset default label (unless user has changed it)
                    If ser.autoLabel Then
                        ser.GetDefaultLabel()
                    End If
                End If
            Next
            SetGraphTitle()
            Zed.AxisChange()
            Zed.Refresh()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Set the current node number for all series
    ''' Used when animating time series plots (BMD only)
    ''' </summary>
    Friend Sub SetSeriesNode(ByVal NodeNum As Integer)
        Try
            For Each ser As clsSeries In _Series
                If ser.IsCalc OrElse (ser.Table.TableType <> clsTable.enumTableType.BMD And ser.Table.TableType <> clsTable.enumTableType.BMD2) Then
                    ser.Visible = False
                Else
                    With CType(ser, clsSeriesTimeSeries)
                        Dim ar() As String = .StationList.Split(";")
                        If NodeNum < ar.Length Then
                            .StationID = ar(NodeNum)
                            '.Visible = True
                            .GetData()
                            .Label = String.Format("{0} at {1}", .PCode, .StationID)
                        Else
                            '.Visible = False
                        End If
                    End With
                End If
            Next
            Zed.Refresh()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    ''' <summary>
    ''' Set the current time window for all series
    ''' </summary>
    Friend Sub SetSeriesTimeWindow(ByVal TimeWindow As enumTimeWindow)
        Try
            For Each ser As clsSeries In _Series
                If Not ser.IsCalc Then
                    Select Case _GraphType
                        Case enumGraphType.Profile
                            CType(ser, clsSeriesLongProfile).TimeWindow = TimeWindow
                        Case enumGraphType.Depth
                            CType(ser, clsSeriesDepthProfile).TimeWindow = TimeWindow
                        Case enumGraphType.Width
                            CType(ser, clsSeriesWidthProfile).TimeWindow = TimeWindow
                        Case enumGraphType.Scatter
                            CType(ser, clsSeriesScatter).TimeWindow = TimeWindow
                        Case Else
                            Exit Sub
                    End Select
                    ser.GetData()
                End If
            Next
            Zed.Refresh()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Friend Sub ZoomExtents(Optional ByVal sender As Object = Nothing, Optional ByVal e As System.EventArgs = Nothing)
        Try
            With Zed
                If ActiveGraphTab() Is Nothing Then Exit Sub
                With .GraphPane
                    For AxisType As clsAxis.enumAxis = clsAxis.enumAxis.XAxis To clsAxis.enumAxis.Y2Axis
                        For AxisNum As Integer = 0 To 4
                            Dim Axis As New clsAxis(Zed, AxisType, AxisNum, ActiveGraphTab.GraphOptions.FontScaleFactor)
                            With Axis
                                .AutoScaleMin = True
                                .AutoScaleMax = True
                                .FixLogScale()
                                If GraphType = enumGraphType.FlowDuration And AxisType = clsAxis.enumAxis.XAxis Then
                                    .Min = 0
                                    .Max = 100
                                End If
                            End With
                        Next
                    Next
                    .IsBoundedRanges = False
                End With
                .AxisChange()
                .IsAutoScrollRange = False
                .ScrollMinX = .GraphPane.XAxis.Scale.Min
                .ScrollMaxX = .GraphPane.XAxis.Scale.Max
                .ScrollMinY = .GraphPane.YAxis.Scale.Min
                .ScrollMaxY = .GraphPane.YAxis.Scale.Max
                .Refresh()
            End With
            GraphForm.pgAxes.Refresh()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Friend Sub ZoomLimits(Optional ByVal sender As Object = Nothing, Optional ByVal e As System.EventArgs = Nothing)
        Try
            With Zed
                With .GraphPane
                    For i As Integer = 1 To 2
                        With CType(Choose(i, .XAxis, .X2Axis), ZedGraph.Axis)
                            SetAxisLimit(clsAxis.AxisExtra(.Tag).MinLimit, .Type, .Scale.MinAuto, .Scale.Min)
                            SetAxisLimit(clsAxis.AxisExtra(.Tag).MaxLimit, .Type, .Scale.MaxAuto, .Scale.Max)
                        End With
                        For j As Integer = 0 To 4
                            With CType(Choose(i, .YAxisList(j), .Y2AxisList(j)), ZedGraph.Axis)
                                SetAxisLimit(clsAxis.AxisExtra(.Tag).MinLimit, .Type, .Scale.MinAuto, .Scale.Min)
                                SetAxisLimit(clsAxis.AxisExtra(.Tag).MaxLimit, .Type, .Scale.MaxAuto, .Scale.Max)
                            End With
                        Next
                    Next
                    .IsBoundedRanges = False
                End With
                .AxisChange()
                .IsAutoScrollRange = False
                .ScrollMinX = .GraphPane.XAxis.Scale.Min
                .ScrollMaxX = .GraphPane.XAxis.Scale.Max
                .ScrollMinY = .GraphPane.YAxis.Scale.Min
                .ScrollMaxY = .GraphPane.YAxis.Scale.Max
                .Refresh()
            End With
            GraphForm.pgAxes.Refresh()
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Sub

    Friend Sub ZoomPrevious(Optional ByVal sender As Object = Nothing, Optional ByVal e As System.EventArgs = Nothing)
        With Zed
            .ZoomOut(.GraphPane)
        End With
        GraphForm.pgAxes.Refresh()
    End Sub

    ''' <summary>
    ''' Detect if minor tick on x-axis is less than one day; if so, add time to format (time series only)
    ''' </summary>
    Private Sub Zed_ZoomEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal oldState As ZedGraph.ZoomState, ByVal newState As ZedGraph.ZoomState) Handles _Zed.ZoomEvent
        GraphForm.pgAxes.Refresh()
        'this doesn't work--scale values are associated with old state, not new, and cannot get ScaleState for some reason; use GraphPan.AxisChangeEventHandler instead
        'If GraphType = enumGraphType.TimeSeries Then
        '    With Zed.GraphPane.XAxis.Scale
        '        Debug.Print(.Min & "," & .Max & "," & .MajorUnit.ToString & "," & .MajorStep)
        '        .Format = "MM/dd/yy"
        '        If .MajorUnit >= DateUnit.Minute Then .Format &= vbCrLf & "HH:mm"
        '    End With
        'End If
    End Sub

    Private Sub Zed_AxisChange(ByVal pane As ZedGraph.GraphPane)
        If GraphType = enumGraphType.TimeSeries Then
            With pane.XAxis.Scale
                If clsAxis.AxisExtra(pane.XAxis.Tag).ScaleType = clsAxis.enumScaleType.Date_Julian Then
                    .Format = MyMonthDayFormat()
                ElseIf clsAxis.AxisExtra(pane.XAxis.Tag).ScaleType = clsAxis.enumScaleType.Date Then
                    .Format = MyDateFormat()
                    If .MajorUnit > DateUnit.Day Then .Format = MyDateTimeFormat()
                End If
            End With
        Else
            pane.XAxis.Scale.Format = ""
        End If
    End Sub

    Private Sub Zed_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles _Zed.KeyUp
        With GraphForm.TabGraph
            If e.KeyCode = Keys.Left Or (e.KeyCode = Keys.PageUp And e.Control) And .SelectedIndex > 0 Then
                .SelectedIndex -= 1
            ElseIf e.KeyCode = Keys.Right Or (e.KeyCode = Keys.PageDown And e.Control) And .SelectedIndex < .TabCount - 2 Then
                .SelectedIndex += 1
            End If
        End With
    End Sub

    Private Function Zed_MouseMoveEvent(ByVal sender As ZedGraph.ZedGraphControl, ByVal e As System.Windows.Forms.MouseEventArgs) As Boolean Handles _Zed.MouseMoveEvent
        Try
            Static LastPt2 As Point
            Static LastTooltip As String = Nothing
            With Zed.GraphPane
                Dim s As String = ""
                Dim x As Double = .XAxis.Scale.ReverseTransform(e.X)
                If x >= .XAxis.Scale.Min And x <= .XAxis.Scale.Max Then
                    If GraphType = enumGraphType.TimeSeries Then
                        s = String.Format("{0} = {1}", .XAxis.Title.Text, Date.FromOADate(x).ToString(MyDateTimeFormat))
                    Else
                        s = String.Format("{0} = {1:N4}", .XAxis.Title.Text, .XAxis.Scale.ReverseTransform(e.X))
                    End If
                    For i As Integer = 0 To 1
                        For j As Integer = 0 To 4
                            With Choose(i + 1, .YAxisList, .Y2AxisList)
                                With CType(.item(j), ZedGraph.Axis)
                                    Dim y As Double = .Scale.ReverseTransform(e.Y)
                                    If y < .Scale.Min Or y > .Scale.Max Then s = "" : Exit For
                                    If .IsVisible Then s &= String.Format("; {0} = {1:N4}", .Title.Text, y)
                                End With
                            End With
                        Next
                    Next
                End If
                If DrawMode = enumDrawMode.FirstPoint Then
                    Select Case DrawType
                        Case enumDrawType.Textbox, enumDrawType.RedrawTextbox
                            s = "Click on upper left corner where auto-sized textbox will be positioned (press ESC to cancel)..."
                        Case Else
                            s = "Click on first point (press ESC to cancel)..."
                    End Select
                    LastPt2 = Point.Empty
                    Zed.Cursor = Cursors.Cross
                ElseIf DrawMode = enumDrawMode.SecondPoint Then
                    Dim pt1 As Point = Zed.PointToScreen(DrawPt1)
                    Dim pt2 As Point = Zed.PointToScreen(LastPt2)
                    Dim pt3 As Point = Zed.PointToScreen(e.Location)
                    Select Case DrawType
                        Case enumDrawType.Arrow, enumDrawType.Line
                            If Not LastPt2.IsEmpty Then ControlPaint.DrawReversibleLine(pt1, pt2, Zed.BackColor)
                            ControlPaint.DrawReversibleLine(pt1, pt3, Zed.BackColor)
                        Case Else
                            If Not LastPt2.IsEmpty Then ControlPaint.DrawReversibleFrame(New Rectangle(pt1.X, pt1.Y, pt2.X - pt1.X, pt2.Y - pt1.Y), Zed.BackColor, FrameStyle.Dashed)
                            ControlPaint.DrawReversibleFrame(New Rectangle(pt1.X, pt1.Y, pt3.X - pt1.X, pt3.Y - pt1.Y), Zed.BackColor, FrameStyle.Dashed)
                    End Select
                    LastPt2 = e.Location
                    s = "Click on second point (press ESC to cancel)..."
                    Zed.Cursor = Cursors.Cross
                Else
                    'set cursor depending on where mouse is
                    With Zed.GraphPane
                        Dim x1, y1 As Double
                        .ReverseTransform(e.Location, x1, y1)
                        'convert to percent screen
                        With .XAxis.Scale
                            x1 = (x1 - .Min) / (.Max - .Min)
                        End With
                        With .YAxis.Scale
                            If .IsLog Then
                                y1 = (Math.Log(y1) - Math.Log(.Min)) / (Math.Log(.Max) - Math.Log(.Min))
                            Else
                                y1 = (y1 - .Min) / (.Max - .Min)
                            End If
                        End With

                        If x1 < 0 OrElse x1 > 1 OrElse y1 <= 0 OrElse y1 > 1 Then 'outside graph area; show arrow
                            Zed.Cursor = Cursors.Arrow
                        Else
                            If GraphOptions.ZoomOption = enumZoomOptions.Auto Then
                                If (y1 >= 0 And y1 < 0.1) Or (y1 <= 1 And y1 > 0.9) Then 'show horizontal cursor if within 10% of bottom or top axis
                                    Zed.Cursor = Cursors.SizeWE
                                ElseIf (x1 >= 0 And x1 < 0.1) Or (x1 <= 1 And x1 > 0.9) Then 'show vertical cursor if within 10% of left or right axis
                                    Zed.Cursor = Cursors.SizeNS
                                Else
                                    Zed.Cursor = Cursors.Arrow
                                End If
                            Else
                                Zed.Cursor = Cursors.Arrow
                            End If
                        End If
                    End With

                    If GraphOptions.ShowPoints Then

                        'show tooltip with nearest object

                        Dim NearestObject As Object = Nothing

                        Dim Index As Integer
                        If Zed.GraphPane.FindNearestObject(New PointF(e.X, e.Y), Zed.CreateGraphics, NearestObject, Index) Then
                            If TypeOf NearestObject Is ZedGraph.LineItem Then
                                With CType(NearestObject, ZedGraph.LineItem)
                                    If .IsVisible Then
                                        Dim s2 As String = .Label.Text & ": "
                                        If GraphType = enumGraphType.TimeSeries Then
                                            s2 &= Date.FromOADate(.Points(Index).X).ToString(MyDateTimeFormat)
                                        Else
                                            s2 &= .Points(Index).X.ToString("N4")
                                        End If
                                        s2 &= String.Format("; {0:N4}", .Points(Index).Y)

                                        If s2 <> LastTooltip Then GraphForm.ToolTip.SetToolTip(Zed, s2)
                                        LastTooltip = s2
                                    Else
                                        If LastTooltip IsNot Nothing Then GraphForm.ToolTip.SetToolTip(Zed, Nothing)
                                        LastTooltip = Nothing
                                    End If

                                End With
                            Else
                                If LastTooltip IsNot Nothing Then GraphForm.ToolTip.SetToolTip(Zed, Nothing)
                                LastTooltip = Nothing
                            End If
                        Else
                            If LastTooltip IsNot Nothing Then GraphForm.ToolTip.SetToolTip(Zed, Nothing)
                            LastTooltip = Nothing
                        End If
                    Else
                        If LastTooltip IsNot Nothing Then GraphForm.ToolTip.SetToolTip(Zed, Nothing)
                        LastTooltip = Nothing
                    End If
                End If
                If s = "" And GraphForm.Statusbar.Text.StartsWith("Zoom/pan") Then Exit Function
                GraphForm.Statusbar.Text = s


                'decide what to return (if true, Zedgraph will not process anything more -- to eliminate mouse flicker)
                If DrawMode = enumDrawMode.None And (e.Button = MouseButtons.Left Or e.Button = MouseButtons.Middle) Then Return False Else Return True
            End With
        Catch ex As Exception
            ErrorMsg(, ex)
        End Try
    End Function

    ''' <summary>
    ''' Workaround for problems associated with access of WDM files
    ''' </summary>
    ''' <param name="tbl">Table reference (if not WDM, will do nothing)</param>
    ''' <remarks>problem with ATCs DLL (?) causes WRDB to crash without warning; following is really a cludge</remarks>
    <DebuggerStepThrough()> _
    Private Sub InitializeWDM(tbl As clsTable)
        If tbl.TableType = clsTable.enumTableType.WRDBData AndAlso (tbl.dsData.DataType = DataSource.clsData.enumDataType.WDM Or tbl.dsData.DataType = DataSource.clsData.enumDataType.HBN) Then
            Try
                Process.Start(tbl.dsData.FileName)
            Catch ex As Exception
            End Try
        End If
    End Sub
End Class
